#!/usr/bin/python3
# -*- coding: utf-8 -*-

# Copyright (C) 2013-2014 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 future import standard_library
standard_library.install_aliases()
from builtins import str
from builtins import object
import csv
import json
import urllib.request, urllib.error, urllib.parse
import urllib.request, urllib.parse, urllib.error

XIVO1 = "192.168.32.70"
XIVO2 = "192.168.32.139"
GATEWAY1 = "xivo-gtw-1"
GATEWAY2 = "xivo-gtw-2"
CONTEXT = "test_incall"

INCALL_URI = "/service/ipbx/json.php/%s/call_management/incall"


class WebServicesResponse(object):
    def __init__(self, url, code, data):
        self.url = url
        self.code = code
        self.data = data


class IncomingCallsWebServices(object):
    def __init__(self, uri_prefix):
        self._wsr = None
        self._path = self._compute_path(uri_prefix)
        self._uri_prefix = uri_prefix
        self._opener = self._build_opener(None, None)
        self._headers = {"Content-type": "application/json",
                         "Accept": "text/plain"}

    def _compute_path(self, uri_prefix):
        if 'localhost' in uri_prefix or '127.0.0.1' in uri_prefix:
            method = 'private'
        else:
            method = 'restricted'
        return INCALL_URI % method

    def _request_http(self, qry, data=None):
        if isinstance(data, dict):
            data = json.dumps(data)
        url = '%s%s?%s' % (self._uri_prefix, self._path, self._build_query(qry))
        request = urllib.request.Request(url=url, data=data, headers=self._headers)
        handle = self._opener.open(request)
        try:
            self._wsr = WebServicesResponse(url, handle.code, handle.read())
        finally:
            handle.close()
        return self._wsr

    def _build_opener(self, username, password):
        handlers = []
        if username is not None or password is not None:
            pwd_manager = urllib.request.HTTPPasswordMgrWithDefaultRealm()
            pwd_manager.add_password(None, self._uri_prefix, username, password)
            handlers.append(urllib.request.HTTPBasicAuthHandler(pwd_manager))
        return urllib.request.build_opener(*handlers)

    def _build_query(self, qry):
        return urllib.parse.urlencode(qry)

    def list(self):
        qry = {"act": "list"}
        return self._request_http(qry)

    def add(self, content):
        qry = {"act": "add"}
        return self._request_http(qry, content)


class IncomingCallsCache(object):
    def __init__(self, incomingcall_ws):
        self.incomingcall_ws = incomingcall_ws

    def init_cache(self):
        response = self.incomingcall_ws.list()
        if response.code == 200:
            incoming_calls = json.loads(response.data)
            self.incalls = dict((incoming_call['exten'], incoming_call) for incoming_call in incoming_calls)
        else:
            self.incalls = {}

    def exists(self, extension):
        return extension in self.incalls


def create_incoming_calls(user_phone_nb, incoming_call_ws, gateway):
    exten = user_phone_nb
    context = CONTEXT

    incall_content = new_incall_content(exten, context, gateway)
    response = incoming_call_ws.add(incall_content)


def new_incall_content(exten, context, gateway):
    return {
        "incall": {
            "exten": str(exten),
            "context": str(context),
            "preprocess_subroutine": "",
        },
        "dialaction": {
            "answer": {
                 "actiontype": "custom",
                 "actionarg1": "Dial(SIP/%s/${XIVO_DSTNUM})" % gateway,
                 "actionarg2": ""
            }
        }
    }


def import_csv(incoming_call_cache1, incoming_call_cache2, incoming_call_ws1, incoming_call_ws2, gateway1, gateway2):
    with open('users.csv', 'rb') as fobj:
        userReader = csv.reader(fobj, delimiter=';', quotechar='|')

    for row in userReader:
        extension = row[3]
        if incoming_call_cache1.exists(extension):
            print("Xivo1 : incoming call already exists for %s " % extension)
        else:
            print("Xivo1 : creating incoming call for %s gateway %s" % (extension, gateway1))
            create_incoming_calls(extension, incoming_call_ws1, gateway1)
        if incoming_call_cache2.exists(extension):
            print("Xivo2 : incoming call already exists for %s " % extension)
        else:
            print("Xivo2 : creating incoming call for %s gateway %s" % (extension, gateway2))
            create_incoming_calls(extension, incoming_call_ws2, gateway2)


def main():
    xivo1 = XIVO1
    xivo2 = XIVO2
    gateway1 = GATEWAY1
    gateway2 = GATEWAY2

    print("--------------creating incoming calls-------------")
    print(" xivo 1 : %s " % xivo1)
    print(" xivo 2 : %s " % xivo2)
    print(" gateway 1 : %s " % gateway1)
    print(" gateway 2 : %s " % gateway2)

    incoming_call_ws1 = IncomingCallsWebServices('https://%s:443' % xivo1)
    incoming_call_ws2 = IncomingCallsWebServices('https://%s:443' % xivo2)

    incoming_call_cache1 = IncomingCallsCache(incoming_call_ws1)
    incoming_call_cache1.init_cache()
    incoming_call_cache2 = IncomingCallsCache(incoming_call_ws2)
    incoming_call_cache2.init_cache()
    import_csv(incoming_call_cache1, incoming_call_cache2, incoming_call_ws1, incoming_call_ws2, gateway1, gateway2)


if __name__ == '__main__':
    main()
