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

# Copyright (C) 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 builtins import map
from xivo_agid import dialplan_variables
from xivo_dao import user_line_dao
from functools import reduce


XFER_VARS = [dialplan_variables.SIPTRANSFER,
             dialplan_variables.BLINDTRANSFER,
             dialplan_variables.ATTENDEDTRANSFER]


def check_call_fwd(agi):
    """
    This function returns a tuple: (is_fwded_activated, fwd_type)

    When a call is forwarded
      - via XiVO extensions (*21, ...)
      - or via XiVO redirection (No answer tab in webi...)
    the variable
      - XIVO_CALLFORWARDED
    should be set

    When a call is forwarded
      - via phone set
    the variable
      - FORWARDERNAME
    should be set (containing the channek name (e.g. SIP/abcd-01234567) of forwarder
    """
    if (agi.get_variable(dialplan_variables.CALLFORWARDED) != ''):
        return (True, "XIVO")
    elif (agi.get_variable(dialplan_variables.FORWARDERNAME) != ''):
        return (True, "SIP")
    else:
        return (False, None)


def is_call_xferred(agi):
    """
    When a call is transferred at least one of the below variables should be set
    SIPTRANSFER:
      - is set when asterisk detects a SIP transfer (via a REFER or replaces header)
      - contains yes or void
    BLINDTRANSFER:
      - is set when asterisk detects a SIP blind transfer (via a REFER)
        or when an asterisk blind transfer feature (*1 by default) is performed
        or when switchboard does blind transfer (it is a Redirect, but ctid sets
           this variable to true in this case)
      - contains Channel name (e.g. SIP/abcd-00000000) of transferer
    ATTENDEDTRANSFER:
      - when an asterisk attended transfer feature code (*2 by default) is performed
      - contains Channel name (e.g. SIP/efgh-00000000) if transferer
    """
    def _check_var_is_set(x): return agi.get_variable(x) != ''

    are_xfer_vars_set = list(map(_check_var_is_set, XFER_VARS))
    is_one_xfer_var_set = reduce(lambda x,y: x or y,
                                  are_xfer_vars_set)

    return is_one_xfer_var_set


def get_user_id(agi):
    """
    This is a helper function to retrieve the 'good' userid depending
    of the call flow.
    When a user is calling we use its userid (set by chan_sip according to the peer configuration)
    to set the CallerID and check the Call permission of the call.
    When there is a forward (U1 calls U2 forwarded to External) we want, when calling External,
    to set U2's CallerID and check U2's Call permission.
    But, in this case, the userid variable might not be set or may be still set to U1's userid.
    Here's come this function.

    TODO: this function could be further expanded to retrieve the 'good' userid in case of transfer.
    """
    userid = agi.get_variable(dialplan_variables.USERID)

    (fwded, fwdtype) = check_call_fwd(agi)

    if fwded:
        if fwdtype == "XIVO":
            referer = agi.get_variable(dialplan_variables.FWD_REFERER)
            if referer.startswith('user'):
                refererid = referer.split(':')[1] if len(referer.split(':')) > 1 else ''
                return refererid
            else:
                return ''
        elif fwdtype == "SIP":
            forwarder = agi.get_variable(dialplan_variables.FORWARDERNAME)
            forwarderid = user_line_dao.get_id_from_channel(forwarder)
            return forwarderid
    else:
        return userid


def get_called_num_for_rights(agi):
    dstnum = ''

    (_, fwdtype) = check_call_fwd(agi)

    if fwdtype == "XIVO":
        fwdaction = agi.get_variable('XIVO_FWD_ACTION')
        if (fwdaction == 'extension'):
            dstnum = agi.get_variable('XIVO_FWD_ACTIONARG1')
        elif (fwdaction == 'user'):
            dstuserid = agi.get_variable('XIVO_FWD_ACTIONARG1')
            dstnum = user_line_dao.get_main_exten_by_user_id(dstuserid)
    elif fwdtype == "SIP":
        dstnum = agi.get_variable(dialplan_variables.DESTINATION_NUMBER)
    else:
        dstnum = agi.get_variable(dialplan_variables.DESTINATION_NUMBER)

    return dstnum
