# -*- coding: UTF-8 -*-

# Copyright (C) 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, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.


import logging
import random
import string

from sqlalchemy import text
from xivo_dao.alchemy.context import Context
from xivo_dao.alchemy.contextinclude import ContextInclude
from xivo_dao.alchemy.contextnumbers import ContextNumbers
from xivo_dao.alchemy.entity import Entity
from xivo_dao.alchemy.func_key_template import FuncKeyTemplate
from xivo_dao.alchemy.general import General
from xivo_dao.alchemy.netiface import Netiface
from xivo_dao.alchemy.resolvconf import Resolvconf
from xivo_dao.alchemy.sccpgeneralsettings import SCCPGeneralSettings
from xivo_dao.alchemy.staticiax import StaticIAX
from xivo_dao.alchemy.staticsip import StaticSIP
from xivo_dao.alchemy.user import User
from xivo_dao.alchemy.userfeatures import UserFeatures
from xivo_dao.helpers.db_manager import Session

log = logging.getLogger(__name__)

DEFAULT_FRENCH_CONFIGURATION_SQL = '/etc/xivo/default_french_configuration.sql'


def set_admin_password(password):
    row = Session.query(User).filter(User.login == 'root').first()
    row.passwd = password
    Session.add(row)


def set_autoprov_name(autoprov_username):
    Session.add(StaticSIP(category='general',
                          filename='sip.conf',
                          var_name='autocreate_prefix',
                          var_val=autoprov_username))


def set_default_entity(display_name, name):
    row = Entity(displayname=display_name, name=name, description='Wizard Entity')
    Session.add(row)


def get_entity(display_name):
    return ''.join(c for c in display_name if c.isalnum()).lower()


def set_language(language):
    row = Session.query(StaticSIP).filter(StaticSIP.var_name == 'language').first()
    row.var_val = language
    Session.add(row)

    row = Session.query(StaticIAX).filter(StaticIAX.var_name == 'language').first()
    row.var_val = language
    Session.add(row)

    row = Session.query(SCCPGeneralSettings).filter(SCCPGeneralSettings.option_name == 'language').first()
    row.option_value = language
    Session.add(row)


def set_timezone(timezone):
    row = Session.query(General).first()
    row.timezone = timezone
    Session.add(row)


def set_resolvconf(hostname, domain, nameservers):
    row = Session.query(Resolvconf).first()
    row.hostname = hostname
    row.domain = domain
    row.search = domain
    row.description = 'Wizard Configuration'
    row.nameserver1 = nameservers[0]
    if len(nameservers) > 1:
        row.nameserver2 = nameservers[1]
        if len(nameservers) > 2:
            row.nameserver3 = nameservers[2]

    Session.add(row)


def set_netiface(interface, address, netmask, gateway):
    Session.add(Netiface(ifname=interface,
                         hwtypeid=1,
                         networktype='voip',
                         type='iface',
                         family='inet',
                         method='static',
                         address=address,
                         netmask=netmask,
                         broadcast='',
                         gateway=gateway,
                         mtu=1500,
                         options='',
                         description='Wizard Configuration'))


def set_context_switchboard(entity):
    Session.add(Context(name='__switchboard_directory',
                        displayname='Switchboard',
                        entity=entity,
                        contexttype='others',
                        description=''))


def set_context_internal(context, entity):
    Session.add(Context(name='default',
                        displayname=context['display_name'],
                        entity=entity,
                        contexttype='internal',
                        description=''))

    Session.add(ContextNumbers(context='default',
                               type='user',
                               numberbeg=context['number_start'],
                               numberend=context['number_end']))


def set_context_incall(context, entity):
    Session.add(Context(name='from-extern',
                        displayname=context['display_name'],
                        entity=entity,
                        contexttype='incall',
                        description=''))

    if context.get('number_start') and context.get('number_end'):
        Session.add(ContextNumbers(context='from-extern',
                                   type='incall',
                                   numberbeg=context['number_start'],
                                   numberend=context['number_end'],
                                   didlength=context['did_length']))


def set_context_outcall(context, entity):
    Session.add(Context(name='to-extern',
                        displayname=context['display_name'],
                        entity=entity,
                        contexttype='outcall',
                        description=''))


def include_outcall_context_in_internal_context():
    Session.add(ContextInclude(context='default',
                               include='to-extern',
                               priority=0))


def set_xivo_configured():
    row = Session.query(General).first()
    row.configured = True
    Session.add(row)


def get_xivo_configured():
    return Session.query(General).first()


def set_handle_system_conf(handle_system_conf):
    row = Session.query(General).first()
    row.handle_system_conf = handle_system_conf
    Session.add(row)


def create(wizard, autoprov_username):
    network = wizard['network']
    entity = get_entity(wizard['entity_name'])

    set_admin_password(wizard['admin_password'])
    set_autoprov_name(autoprov_username)
    set_default_entity(wizard['entity_name'], entity)
    if (wizard['default_french_configuration']):
        set_language('fr_FR')
    else:
        set_language(wizard['language'])

    set_netiface(network['interface'], network['ip_address'], network['netmask'], network['gateway'])
    set_resolvconf(network['hostname'], network['domain'], network['nameservers'])
    set_timezone(wizard['timezone'])
    set_context_switchboard(entity)
    set_context_incall(wizard['context_incall'], entity)
    set_context_internal(wizard['context_internal'], entity)
    set_context_outcall(wizard['context_outcall'], entity)
    include_outcall_context_in_internal_context()
    if (wizard['default_french_configuration']):
        apply_default_french_configuration()
    create_xuc_func_key_template()
    create_user_xuc()


def apply_default_french_configuration():
    log.info("Applying default french configuration.")
    config_file = open(DEFAULT_FRENCH_CONFIGURATION_SQL, 'r')
    sql_command = ''

    for line in config_file:
        if not line.startswith('--') and line.strip('\n'):
            sql_command += line.strip('\n')

            if sql_command.endswith(';'):
                try:
                    Session.execute(text(sql_command))
                except:
                    log.error("Unable to insert: %s", sql_command)
                finally:
                    try:
                        Session.commit()
                    except:
                        log.error("Unable to commit: %s", sql_command)
                    finally:
                        sql_command = ''

    row = Session.query(StaticSIP).filter(StaticSIP.var_name == 'dtmfmode').first()
    row.var_val = 'info'
    Session.add(row)

    row = Session.query(StaticSIP).filter(StaticSIP.var_name == 'trustrpid').first()
    row.var_val = 'yes'
    Session.add(row)

    row = Session.query(StaticSIP).filter(StaticSIP.var_name == 'sendrpid').first()
    row.var_val = 'pai'
    Session.add(row)

    row = Session.query(StaticSIP).filter(StaticSIP.var_name == 'allow').first()
    row.commented = 0
    row.var_val = 'alaw,g722,g729,h264'
    Session.add(row)


def create_xuc_func_key_template():
    Session.add(FuncKeyTemplate(name='xuc technical',
                                private=True))


def generate_password(length=32):
    pool = string.digits + string.ascii_letters + string.punctuation
    return ''.join(random.choice(pool) for _ in range(length))


def create_user_xuc():
    xuc_func_key_template = Session.query(FuncKeyTemplate).filter(FuncKeyTemplate.name == 'xuc technical').first()

    Session.add(UserFeatures(firstname='xuc',
                             email='',
                             agentid=0,
                             pictureid=0,
                             entityid=1,
                             callerid='xuc',
                             ringseconds=30,
                             simultcalls=5,
                             enableclient=1,
                             loginclient='xuc',
                             passwdclient=generate_password(),
                             cti_profile_id=1,
                             enablehint=1,
                             enablevoicemail=0,
                             enablexfer=1,
                             enableonlinerec=0,
                             callrecord=0,
                             incallfilter=0,
                             enablednd=0,
                             enableunc=0,
                             destunc='',
                             enablerna=0,
                             destrna='',
                             enablebusy=0,
                             destbusy='',
                             musiconhold='default',
                             outcallerid='default',
                             mobilephonenumber='',
                             bsfilter='no',
                             preprocess_subroutine='',
                             timezone='',
                             language='',
                             ringintern='',
                             ringextern='',
                             ringgroup='',
                             ringforward='',
                             rightcallcode='',
                             commented=0,
                             func_key_private_template_id=xuc_func_key_template.id,
                             lastname='technical',
                             userfield='',
                             description=''))
