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

# Copyright (C) 2014-2018 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 sqlalchemy.orm import aliased
from sqlalchemy.sql import func, case

from xivo_dao.alchemy import Labels
from xivo_dao.alchemy.agentfeatures import AgentFeatures
from xivo_dao.alchemy.entity import Entity
from xivo_dao.alchemy.extension import Extension
from xivo_dao.alchemy.linefeatures import LineFeatures as Line
from xivo_dao.alchemy.user_line import UserLine
from xivo_dao.alchemy.userfeatures import UserFeatures as User
from xivo_dao.alchemy.usersip import UserSIP
from xivo_dao.alchemy.voicemail import Voicemail
from xivo_dao.resources.user.model import UserModel, UserDirectory, UserSummary
from xivo_dao.resources.utils.view import ViewSelector, View


class UserView(View):

    def query(self, session):
        grouped_labels = aliased(
            session.query(
                User.id.label('user_id'),
                func.array_agg(Labels.id).label('labels')
            )
                .join(User.labels)
                .group_by(User.id)
                .subquery()
        )

        query = (session.query(User.id.label('id'),
                               User.uuid.label('uuid'),
                               User.firstname.label('firstname'),
                               func.nullif(User.lastname, '').label('lastname'),
                               func.nullif(User.email, '').label('email'),
                               func.nullif(User.timezone, '').label('timezone'),
                               func.nullif(User.language, '').label('language'),
                               func.nullif(User.description, '').label('description'),
                               func.nullif(User.callerid, '').label('caller_id'),
                               func.nullif(User.outcallerid, '').label('outgoing_caller_id'),
                               func.nullif(User.mobilephonenumber, '').label('mobile_phone_number'),
                               func.nullif(User.loginclient, '').label('username'),
                               func.nullif(User.passwdclient, '').label('password'),
                               func.nullif(User.musiconhold, '').label('music_on_hold'),
                               func.nullif(User.preprocess_subroutine, '').label('preprocess_subroutine'),
                               func.nullif(User.userfield, '').label('userfield'),
                               case([(User.enablexfer == 1, True)],
                                    else_=False).label('call_transfer_enabled'),
                               case([(User.callrecord == 1, True)],
                                    else_=False).label('call_record_enabled'),
                               case([(User.enableonlinerec == 1, True)],
                                    else_=False).label('online_call_record_enabled'),
                               case([(User.enablehint == 1, True)],
                                    else_=False).label('supervision_enabled'),
                               User.ringseconds.label('ring_seconds'),
                               User.simultcalls.label('simultaneous_calls'),
                               func.nullif(User.rightcallcode, '').label('call_permission_password'),
                               case([(User.commented == 0, True)],
                                    else_=False).label('enabled'),
                               func.nullif(AgentFeatures.number, '').label('agent_number'),
                               User.agentid.label('agentid'),
                               AgentFeatures.numgroup.label('agent_group_id'),
                               grouped_labels.c.labels)
                 .outerjoin(grouped_labels,
                            User.id == grouped_labels.c.user_id))
        return query

    def convert(self, row):
        return UserModel(id=row.id,
                         uuid=row.uuid,
                         firstname=row.firstname,
                         lastname=row.lastname,
                         email=row.email,
                         timezone=row.timezone,
                         language=row.language,
                         description=row.description,
                         caller_id=row.caller_id,
                         outgoing_caller_id=row.outgoing_caller_id,
                         mobile_phone_number=row.mobile_phone_number,
                         username=row.username,
                         password=row.password,
                         music_on_hold=row.music_on_hold,
                         preprocess_subroutine=row.preprocess_subroutine,
                         userfield=row.userfield,
                         call_transfer_enabled=row.call_transfer_enabled,
                         call_record_enabled=row.call_record_enabled,
                         online_call_record_enabled=row.online_call_record_enabled,
                         supervision_enabled=row.supervision_enabled,
                         ring_seconds=row.ring_seconds,
                         simultaneous_calls=row.simultaneous_calls,
                         call_permission_password=row.call_permission_password,
                         agent_number=row.agent_number,
                         agentid=row.agentid,
                         agent_group_id=row.agent_group_id,
                         enabled=row.enabled,
                         labels=[] if row.labels is None else row.labels)


class DirectoryView(View):

    def query(self, session):
        query = (session.query(User.id.label('id'),
                               User.uuid.label('uuid'),
                               UserLine.line_id.label('line_id'),
                               User.agentid.label('agent_id'),
                               User.firstname.label('firstname'),
                               func.nullif(User.lastname, '').label('lastname'),
                               func.nullif(User.email, '').label('email'),
                               func.nullif(User.mobilephonenumber, '').label('mobile_phone_number'),
                               Voicemail.mailbox.label('voicemail_number'),
                               func.nullif(User.userfield, '').label('userfield'),
                               func.nullif(User.description, '').label('description'),
                               Extension.exten.label('exten'),
                               Extension.context.label('context')))
        return query

    def convert(self, row):
        return UserDirectory(id=row.id,
                             uuid=row.uuid,
                             line_id=row.line_id,
                             agent_id=row.agent_id,
                             firstname=row.firstname,
                             lastname=row.lastname,
                             email=row.email,
                             mobile_phone_number=row.mobile_phone_number,
                             voicemail_number=row.voicemail_number,
                             exten=row.exten,
                             userfield=row.userfield,
                             description=row.description,
                             context=row.context)


class SummaryView(View):

    def query(self, session):
        query = (session.query(User.id.label('id'),
                               User.uuid.label('uuid'),
                               User.firstname.label('firstname'),
                               func.nullif(User.lastname, '').label('lastname'),
                               User.enabled.label('enabled'),
                               case([
                                   (Line.endpoint == "sip", Line.provisioning_code)
                               ],
                                   else_=None).label('provisioning_code'),
                               case([
                                   (Line.endpoint == "sip", UserSIP._options)
                               ],
                                   else_=None).label('sip_options'),
                               Line.endpoint.label('protocol'),
                               Extension.exten.label('extension'),
                               Extension.context.label('context'),
                               Entity.name.label('entity'),
                               Line.configregistrar.label('configregistrar'))
                 )
        return query

    def convert(self, row):
        line_type = self.convert_options_to_line_type(row)
        return UserSummary(id=row.id,
                           uuid=row.uuid,
                           firstname=row.firstname,
                           lastname=row.lastname,
                           enabled=row.enabled,
                           provisioning_code=row.provisioning_code,
                           protocol=row.protocol,
                           extension=row.extension,
                           context=row.context,
                           entity=row.entity,
                           configregistrar=row.configregistrar,
                           line_type=line_type)

    def convert_options_to_line_type(self, row):
        line_type = row.protocol
        if hasattr(row, 'sip_options') and row.sip_options:
            sip_options = [opt for sublist in row.sip_options for opt in sublist]
            line_type = next(iter(sip_options[1:]), line_type)
            line_type_switch = {
                "ua": "ua",
                "yes": "webrtc",
            }
            line_type = line_type_switch.get(line_type, line_type)
        return line_type


user_view = ViewSelector(default=UserView(),
                         user=UserView(),
                         directory=DirectoryView(),
                         summary=SummaryView())
