# -*- coding: utf-8 -*-
# vStream https://github.com/Kodi-vStream/venom-xbmc-addons
#
# alors la j'ai pas le courage
import re
import ssl
from collections import OrderedDict

from requests.adapters import HTTPAdapter

from resources.lib.comaddon import VSlog
from resources.lib.config import GestionCookie
from resources.lib.util import urlEncode

try:  # Python 2
    from urlparse import urlparse
except ImportError:  # Python 3
    from urllib.parse import urlparse

# old version
from requests.packages.urllib3.util.ssl_ import create_urllib3_context

# #####################################################################################################################
#
# Ok so a big thx to VeNoMouS for this code
# From this url https://github.com/VeNoMouS/cloudscraper
# Franchement si vous etes content de voir revenir vos sites allez mettre une etoile sur son github.
#
# #####################################################################################################################


class CipherSuiteAdapter(HTTPAdapter):

    def __init__(self, cipherSuite=None, **kwargs):
        self.cipherSuite = cipherSuite

        if hasattr(ssl, 'PROTOCOL_TLS'):
            self.ssl_context = create_urllib3_context(
                    ssl_version=getattr(ssl, 'PROTOCOL_TLSv1_3', ssl.PROTOCOL_TLSv1_2),
                    ciphers=self.cipherSuite
                    )
        else:
            self.ssl_context = create_urllib3_context(ssl_version=ssl.PROTOCOL_TLSv1)

        super(CipherSuiteAdapter, self).__init__(**kwargs)

    def init_poolmanager(self, *args, **kwargs):
        kwargs['ssl_context'] = self.ssl_context
        return super(CipherSuiteAdapter, self).init_poolmanager(*args, **kwargs)

    def proxy_manager_for(self, *args, **kwargs):
        kwargs['ssl_context'] = self.ssl_context
        return super(CipherSuiteAdapter, self).proxy_manager_for(*args, **kwargs)

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


Mode_Debug = True

if False:
    Mode_Debug = True
    import logging
    # These two lines enable debugging at httplib level (requests->urllib3->http.client)
    # You will see the REQUEST, including HEADERS and DATA, and RESPONSE with HEADERS but without DATA.
    # The only thing missing will be the response.body which is not logged.
    try:
        import http.client as http_client
    except ImportError:
        # Python 2
        import httplib as http_client
    http_client.HTTPConnection.debuglevel = 1

    # You must initialize logging, otherwise you'll not see debug output.
    logging.basicConfig()
    logging.getLogger().setLevel(logging.DEBUG)
    requests_log = logging.getLogger('requests.packages.urllib3')
    requests_log.setLevel(logging.DEBUG)
    requests_log.propagate = True

# ---------------------------------------------------------
# Gros probleme, mais qui a l'air de passer
# Le headers 'Cookie' apparait 2 fois, il faudrait lire la precedente valeur
# la supprimer et remettre la nouvelle avec les 2 cookies
# Non conforme au protocole, mais ca marche (pour le moment)
# -----------------------------------------------------------

# Cookie path
# C:\Users\BRIX\AppData\Roaming\Kodi\userdata\addon_data\plugin.video.matrix\

# Light method
# Ne marche que si meme user-agent
    # req = urllib.request.Request(sUrl, None, headers)
    # try:
        # response = urllib.request.urlopen(req)
        # sHtmlContent = response.read()
        # response.close()
    # except urllib.error.HTTPError as e:
        # if e.code == 503:
            # if CloudflareBypass().check(e.headers):
                # cookies = e.headers['Set-Cookie']
                # cookies = cookies.split(';')[0]
                # sHtmlContent = CloudflareBypass().GetHtml(sUrl, e.read(), cookies)

# Heavy method
# sHtmlContent = CloudflareBypass().GetHtml(sUrl)

# For memory
# http://www.jsfuck.com/

UA = 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:63.0) Gecko/20100101 Firefox/63.0'


class CloudflareBypass(object):
    def __init__(self):
        self.state = False
        self.HttpReponse = None
        self.Memorised_Headers = None
        self.Memorised_PostData = None
        self.Memorised_Cookies = None
        self.Header = None
        self.RedirectionUrl = None

    # Return param for head
    def GetHeadercookie(self, url):
        Domain = re.sub(r'https*:\/\/([^/]+)(\/*.*)', '\\1', url)
        cook = GestionCookie().Readcookie(Domain.replace('.', '_'))
        if cook == '':
            return ''

        return '|' + urlEncode({'User-Agent': UA, 'Cookie': cook})

    def ParseCookies(self, data):
        list = {}

        sPattern = '(?:^|[,;]) *([^;,]+?)=([^;,\/]+)'
        aResult = re.findall(sPattern, data)
        if aResult:
            for cook in aResult:
                if 'deleted' in cook[1]:
                    continue
                list[cook[0]] = cook[1]
                # cookies = cookies + cook[0] + '=' + cook[1]+ ';'

        return list

    def SetHeader(self):
        head = OrderedDict()
        # Need to use correct order
        h = ['User-Agent', 'Accept', 'Accept-Language', 'Accept-Encoding', 'Connection', 'Upgrade-Insecure-Requests']
        v = [UA, 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'en-US,en;q=0.5', 'gzip, deflate', 'close', '1']
        for i in enumerate(h):
            k = checklowerkey(i[1], self.Memorised_Headers)
            if k:
                head[i[1]] = self.Memorised_Headers[k]
            else:
                head[i[1]] = v[i[0]]

        # optional headers
        if 'Referer' in self.Memorised_Headers:
            head['Referer'] = self.Memorised_Headers['Referer']

        if False:
            # Normalisation because they are not case sensitive:
            Headers = ['User-Agent', 'Accept', 'Accept-Language', 'Accept-Encoding', 'Cache-Control', 'Dnt', 'Pragma', 'Connexion']
            Headers_l = [x.lower() for x in Headers]
            head2 = dict(head)
            for key in head2:
                if key not in Headers and key.lower() in Headers_l:
                    p = Headers_l.index(key.lower())
                    head[Headers[p]] = head[key]
                    del head[key]

        return head

    def GetReponseInfo(self):
        return self.RedirectionUrl, self.Header

    def GetHtml(self, url, htmlcontent='', cookies='', postdata=None, Gived_headers=''):

        # Memorise headers
        self.Memorised_Headers = Gived_headers

        # Memorise postdata
        self.Memorised_PostData = postdata

        # Memorise cookie
        self.Memorised_Cookies = cookies

        # cookies in headers?
        if Gived_headers != '':
            if Gived_headers.get('Cookie', None):
                if cookies:
                    self.Memorised_Cookies = cookies + '; ' + Gived_headers.get('Cookie')
                else:
                    self.Memorised_Cookies = Gived_headers['Cookie']

        # For debug
        if Mode_Debug:
            VSlog('Headers present ' + str(Gived_headers))
            VSlog('url ' + url)
            if htmlcontent:
                VSlog('code html ok')
            VSlog('cookies passés : ' + self.Memorised_Cookies)
            VSlog('post data :' + str(postdata))

        self.hostComplet = re.sub(r'(https*:\/\/[^/]+)(\/*.*)', '\\1', url)
        self.host = re.sub(r'https*:\/\/', '', self.hostComplet)
        self.url = url

        cookieMem = GestionCookie().Readcookie(self.host.replace('.', '_'))
        if not (cookieMem == ''):
            if Mode_Debug:
                VSlog('cookies present sur disque :' + cookieMem)
            if not self.Memorised_Cookies:
                cookies = cookieMem
            else:
                cookies = self.Memorised_Cookies + '; ' + cookieMem
        else:
            if Mode_Debug:
                VSlog('Pas de cookies présent sur disque')

        data = {}
        if postdata:
            method = 'POST'
            # Need to convert data to dictionnary
            d = postdata.split('&')
            for dd in d:
                ddd = dd.split('=')
                data[ddd[0]] = ddd[1]
        else:
            method = 'GET'

        from resources.lib import cloudscrape

        s = cloudscrape.create_scraper(browser={'custom': 'ScraperBot/1.0'})

        r = s.request(method, url, headers=self.SetHeader(), cookies=self.ParseCookies(cookies), data=data)
        # r = s.request(method, url)
        MemCookie = r.cookies.get_dict()

        if r:
            sContent = r.text.encode('utf-8')
            self.RedirectionUrl = r.url
            self.Header = r.headers
            VSlog('Page ok')
        else:
            VSlog('Erreur, delete cookie')
            sContent = ''
            # self.RedirectionUrl = r.url
            # self.Header = r.headers
            MemCookie = {}
            # r.cookies.clear()
            GestionCookie().DeleteCookie(self.host.replace('.', '_'))

        # fh = open('c:\\test.txt', 'w')
        # fh.write(sContent)
        # fh.close()

        # Memorisation des cookies
        c = ''
        cookie = MemCookie
        if cookie:
            for i in cookie:
                c = c + i + '=' + cookie[i] + ';'
            # Write them
            GestionCookie().SaveCookie(self.host.replace('.', '_'), c)
            if Mode_Debug:
                VSlog('Sauvegarde cookies: ' + str(c))

        return sContent


def checklowerkey(key, dict):
    for i in dict:
        if str(i.lower()) == str(key.lower()):
            return i
    return False


def checkpart(s, end='+'):
    p = 0
    pos = 0

    try:
        while 1:
            c = s[pos]

            if (c == '('):
                p = p + 1
            if (c == ')'):
                p = p - 1

            pos = pos + 1

            if (c == end) and (p == 0) and (pos > 1):
                break
    except:
        pass

    return s[:pos]


def CheckIfActive(data):
    if 'Checking your browser before accessing' in str(data):
        return True
    return False


def showInfo(sTitle, sDescription, iSeconds=0):
    if (iSeconds == 0):
        iSeconds = 1000
    else:
        iSeconds = iSeconds * 1000
