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

##################################################################################################

import json
import requests
import logging

import utils
import clientinfo

##################################################################################################

# Disable requests logging
from requests.packages.urllib3.exceptions import InsecureRequestWarning, InsecurePlatformWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
requests.packages.urllib3.disable_warnings(InsecurePlatformWarning)
#logging.getLogger('requests').setLevel(logging.WARNING)

##################################################################################################


class ConnectUtils():

    # Borg - multiple instances, shared state
    _shared_state = {}
    clientInfo = clientinfo.ClientInfo()
    addonName = clientInfo.getAddonName()

    # Requests session
    c = None
    timeout = 30


    def __init__(self):

        self.__dict__ = self._shared_state

    def logMsg(self, msg, lvl=1):

        className = self.__class__.__name__
        utils.logMsg("%s %s" % (self.addonName, className), msg, lvl)


    def setUserId(self, userId):
        # Reserved for userclient only
        self.userId = userId
        self.logMsg("Set connect userId: %s" % userId, 2)

    def setServer(self, server):
        # Reserved for userclient only
        self.server = server
        self.logMsg("Set connect server: %s" % server, 2)

    def setToken(self, token):
        # Reserved for userclient only
        self.token = token
        self.logMsg("Set connect token: %s" % token, 2)


    def startSession(self):

        self.deviceId = self.clientInfo.getDeviceId()

        # User is identified from this point
        # Attach authenticated header to the session
        verify = False
        header = self.getHeader()

        # If user enabled host certificate verification
        try:
            verify = self.sslverify
            if self.sslclient is not None:
                verify = self.sslclient
        except:
            self.logMsg("Could not load SSL settings.", 1)

        # Start session
        self.c = requests.Session()
        self.c.headers = header
        self.c.verify = verify
        # Retry connections to the server
        self.c.mount("http://", requests.adapters.HTTPAdapter(max_retries=1))
        self.c.mount("https://", requests.adapters.HTTPAdapter(max_retries=1))

        self.logMsg("Requests session started on: %s" % self.server, 1)

    def stopSession(self):
        try:
            self.c.close()
        except Exception as e:
            self.logMsg("Requests session could not be terminated: %s" % e, 1)

    def getHeader(self, authenticate=True):

        version = self.clientInfo.getVersion()

        if not authenticate:
            # If user is not authenticated
            header = {

                'X-Application': "Kodi/%s" % version,
                'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
                'Accept': "application/json"
            }
            self.logMsg("Header: %s" % header, 1)

        else:
            token = self.token
            # Attached to the requests session
            header = {

                'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
                'Accept': "application/json",
                'X-Application': "Kodi/%s" % version,
                'X-Connect-UserToken': token
            }
            self.logMsg("Header: %s" % header, 1)

        return header

    def doUrl(self, url, data=None, postBody=None, rtype="GET",
                parameters=None, authenticate=True, timeout=None):

        window = utils.window

        self.logMsg("=== ENTER connectUrl ===", 2)
        default_link = ""
        if timeout is None:
            timeout = self.timeout

        # Get requests session
        try:
            # If connect user is authenticated
            if authenticate:
                try:
                    c = self.c
                    # Replace for the real values
                    url = url.replace("{server}", self.server)
                    url = url.replace("{UserId}", self.userId)

                    # Prepare request
                    if rtype == "GET":
                        r = c.get(url, json=postBody, params=parameters, timeout=timeout)
                    elif rtype == "POST":
                        r = c.post(url, data=data, timeout=timeout)
                    elif rtype == "DELETE":
                        r = c.delete(url, json=postBody, timeout=timeout)

                except AttributeError:
                    # request session does not exists
                    self.server = "https://connect.emby.media/service"
                    self.userId = window('embyco_currUser')
                    self.token = window('embyco_accessToken%s' % self.userId)

                    header = self.getHeader()
                    verifyssl = False

                    # If user enables ssl verification
                    try:
                        verifyssl = self.sslverify
                        if self.sslclient is not None:
                            verifyssl = self.sslclient
                    except AttributeError:
                        pass

                    # Prepare request
                    if rtype == "GET":
                        r = requests.get(url,
                                        json=postBody,
                                        params=parameters,
                                        headers=header,
                                        timeout=timeout,
                                        verify=verifyssl)

                    elif rtype == "POST":
                        r = requests.post(url,
                                        data=data,
                                        headers=header,
                                        timeout=timeout,
                                        verify=verifyssl)
            # If user is not authenticated
            else:
                header = self.getHeader(authenticate=False)
                verifyssl = False

                # If user enables ssl verification
                try:
                    verifyssl = self.sslverify
                    if self.sslclient is not None:
                        verifyssl = self.sslclient
                except AttributeError:
                    pass

                # Prepare request
                if rtype == "GET":
                    r = requests.get(url,
                                    json=postBody,
                                    params=parameters,
                                    headers=header,
                                    timeout=timeout,
                                    verify=verifyssl)

                elif rtype == "POST":
                    r = requests.post(url,
                                    data=data,
                                    headers=header,
                                    timeout=timeout,
                                    verify=verifyssl)

            ##### THE RESPONSE #####
            self.logMsg(r.url, 1)
            self.logMsg(r, 1)

            if r.status_code == 204:
                # No body in the response
                self.logMsg("====== 204 Success ======", 1)

            elif r.status_code == requests.codes.ok:

                try:
                    # UNICODE - JSON object
                    r = r.json()
                    self.logMsg("====== 200 Success ======", 1)
                    self.logMsg("Response: %s" % r, 1)
                    return r

                except:
                    if r.headers.get('content-type') != "text/html":
                        self.logMsg("Unable to convert the response for: %s" % url, 1)
            else:
                r.raise_for_status()

        ##### EXCEPTIONS #####

        except requests.exceptions.ConnectionError as e:
            # Make the addon aware of status
            pass

        except requests.exceptions.ConnectTimeout as e:
            self.logMsg("Server timeout at: %s" % url, 0)
            self.logMsg(e, 1)

        except requests.exceptions.HTTPError as e:

            if r.status_code == 401:
                # Unauthorized
                pass

            elif r.status_code in (301, 302):
                # Redirects
                pass
            elif r.status_code == 400:
                # Bad requests
                pass

        except requests.exceptions.SSLError as e:
            self.logMsg("Invalid SSL certificate for: %s" % url, 0)
            self.logMsg(e, 1)

        except requests.exceptions.RequestException as e:
            self.logMsg("Unknown error connecting to: %s" % url, 0)
            self.logMsg(e, 1)

        return default_link