# -*- coding: utf-8 -*-

# Copyright (C) 2011-2016 Avencall
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>

from __future__ import print_function
from builtins import str
from builtins import object
from operator import itemgetter

from xivo_confgen.generators.util import format_ast_section, \
    format_ast_option, format_ast_section_tpl, format_ast_section_using_tpl
from xivo_dao import asterisk_conf_dao


class SccpConf(object):

    def __init__(self, nova_compatibility=False):
        self._nova_compatibility = nova_compatibility
        self._sccpgeneralsettings = asterisk_conf_dao.find_sccp_general_settings()
        self._sccpline = asterisk_conf_dao.find_sccp_line_settings()
        self._sccpdevice = asterisk_conf_dao.find_sccp_device_settings()
        self._sccpspeeddial = asterisk_conf_dao.find_sccp_speeddial_settings()

    def generate(self, output):
        splitted_settings = _SplittedGeneralSettings.new_from_dao_general_settings(self._sccpgeneralsettings)

        sccp_general_conf = _SccpGeneralSettingsConf()
        sccp_general_conf.generate(splitted_settings.general_items, output)

        sccp_device_conf = _SccpDeviceConf(self._sccpspeeddial)
        sccp_device_conf.generate(self._sccpdevice, splitted_settings.device_items, output)

        sccp_line_conf = _SccpLineConf(nova_compatibility=self._nova_compatibility)
        sccp_line_conf.generate(self._sccpline, splitted_settings.line_items, output)

        sccp_speeddial_conf = _SccpSpeedDialConf()
        sccp_speeddial_conf.generate(self._sccpspeeddial, output)


class _SplittedGeneralSettings(object):

    _DEVICE_OPTIONS = ['dialtimeout', 'dateformat', 'vmexten', 'keepalive']
    _LINES_OPTIONS = ['context', 'language', 'directmedia', 'tos_audio', 'disallow', 'allow']

    def __init__(self, general_items, device_items, line_items):
        self.general_items = general_items
        self.device_items = device_items
        self.line_items = line_items

    @classmethod
    def new_from_dao_general_settings(cls, sccp_general_settings):
        general_items = []
        device_items = []
        line_items = []

        for item in sccp_general_settings:
            option_name = item['option_name']
            if option_name in cls._DEVICE_OPTIONS:
                device_items.append(item)
            elif option_name in cls._LINES_OPTIONS:
                line_items.append(item)
            else:
                general_items.append(item)

        return cls(general_items, device_items, line_items)


class _SccpGeneralSettingsConf(object):

    def generate(self, general_items, output):
        print(u'[general]', file=output)
        for item in general_items:
            print(format_ast_option(item['option_name'], item['option_value']), file=output)
        print(file=output)


class _SccpDeviceConf(object):

    _TPL_NAME = 'xivo_device_tpl'

    def __init__(self, sccpspeeddialdevices):
        self._sccpspeeddialdevices = sorted(
            sccpspeeddialdevices,
            key=itemgetter('fknum'),
        )

    def generate(self, sccpdevice, general_device_items, output):
        self._generate_template(general_device_items, output)
        self._generate_devices(sccpdevice, output)

    def _generate_template(self, device_items, output):
        print(format_ast_section_tpl(self._TPL_NAME), file=output)
        for item in device_items:
            print(format_ast_option(item['option_name'], item['option_value']), file=output)
        print(file=output)

    def _generate_devices(self, sccpdevice, output):
        for item in sccpdevice:
            print(format_ast_section_using_tpl(item['name'], self._TPL_NAME), file=output)
            print(format_ast_option('type', 'device'), file=output)
            if item['line']:
                print(format_ast_option('line', item['line']), file=output)
            if item['voicemail']:
                print(format_ast_option('voicemail', item['voicemail']), file=output)
            self._generate_speeddials(output, item['device'])
            print(file=output)

    def _generate_speeddials(self, output, device):
        for item in self._sccpspeeddialdevices:
            if item['device'] == device:
                print(format_ast_option('speeddial', '%d-%d' % (item['user_id'], item['fknum'])), file=output)


class _SccpLineConf(object):

    _TPL_NAME = 'xivo_line_tpl'

    def __init__(self, nova_compatibility):
        self._nova_compatibility = nova_compatibility

    def generate(self, sccplines, general_line_items, output):
        self._generate_template(general_line_items, output)
        self._generate_lines(sccplines, output)

    def _generate_template(self, line_items, output):
        print(format_ast_section_tpl(self._TPL_NAME), file=output)
        for item in line_items:
            option_name = item['option_name']
            option_value = item['option_value']

            if option_name == 'allow':
                if not option_value:
                    continue
                print(format_ast_option('disallow', 'all'), file=output)
            elif option_name == 'disallow':
                continue
            elif option_name == 'directmedia':
                option_value = '0' if option_value == 'no' else '1'

            print(format_ast_option(option_name, option_value), file=output)
        print(file=output)

    def _generate_lines(self, sccplines, output):
        for item in sccplines:
            print(format_ast_section_using_tpl(item['name'], self._TPL_NAME), file=output)
            print(format_ast_option('type', 'line'), file=output)
            print(format_ast_option('cid_name', item['cid_name']), file=output)
            print(format_ast_option('cid_num', item['cid_num']), file=output)
            print(format_ast_option('setvar', 'XIVO_USERID=%s' % item['user_id']), file=output)
            print(format_ast_option('setvar', 'XIVO_USERUUID=%s' % item['uuid']), file=output)
            print(format_ast_option('setvar', 'PICKUPMARK=%(number)s%%%(context)s' % item), file=output)
            print(format_ast_option('setvar', 'TRANSFER_CONTEXT=%s' % item['context']), file=output)
            print(format_ast_option('setvar', 'CHANNEL(hangup_handler_push)=hangup_handlers,userevent,1'), file=output)
            if item['language']:
                print(format_ast_option('language', item['language']), file=output)
            print(format_ast_option('context', item['context']), file=output)
            if 'disallow' in item:
                print(format_ast_option('disallow', item['disallow']), file=output)
            if 'allow' in item:
                print(format_ast_option('allow', item['allow']), file=output)
            if 'callgroup' in item:
                print(format_ast_option('namedcallgroup', ','.join(str(i) for i in item['callgroup'])), file=output)
            if 'pickupgroup' in item:
                print(format_ast_option('namedpickupgroup', ','.join(str(i) for i in item['pickupgroup'])), file=output)
            if self._nova_compatibility:
                print(format_ast_option('accountcode', item['number']), file=output)

            print(file=output)


class _SccpSpeedDialConf(object):
    def generate(self, sccpspeeddial, output):
        for item in sccpspeeddial:
            print(format_ast_section('%d-%d' % (item['user_id'], item['fknum'])), file=output)
            print(format_ast_option('type', 'speeddial'), file=output)
            print(format_ast_option('extension', item['exten']), file=output)
            if item['label']:
                print(format_ast_option('label', item['label']), file=output)
            print(format_ast_option('blf', item['supervision']), file=output)
            print(file=output)
