# -*- coding: utf-8 -*-
# *************************************************************************************************************************
# from Shani's LPro Code https://github.com/Shani-08/ShaniXBMCWork2/blob/master/other/unCaptcha.py
# and https://github.com/OpenMediaVault-Plugin-Developers/openmediavault-pyload/blob/master/usr/share/pyload/module/plugins/captcha/ReCaptcha.py
# and https://gitlab.com/iptvplayer-for-e2/iptvplayer-for-e2
# *************************************************************************************************************************

try:  # Python 2
    import urllib2

except ImportError:  # Python 3
    import urllib.request as urllib2

import base64

try:
    from http.cookiejar import CookieJar
except ImportError:
    from cookielib import CookieJar
    
import os
import random
import re
import time
import xbmcaddon
import xbmcvfs
import xbmcgui
import xbmc

from resources.lib.comaddon import dialog, VSlog
from resources.lib.handler.requestHandler import cRequestHandler
from resources.lib.util import urlEncode, Noredirection

UA = 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:53.0) Gecko/20100101 Firefox/53.0'
__addon__ = xbmcaddon.Addon('plugin.video.matrix')
__sLang__ = 'fr'


class cInputWindow(xbmcgui.WindowDialog):
    def __init__(self, *args, **kwargs):

        self.cptloc = kwargs.get('captcha')
        # self.img = xbmcgui.ControlImage(250, 110, 780, 499, '')
        # xbmc.sleep(500)
        self.img = xbmcgui.ControlImage(250, 110, 780, 499, self.cptloc)
        xbmc.sleep(500)

        bg_image = os.path.join(__addon__.getAddonInfo('path'), 'resources/art/') + 'background.png'
        check_image = os.path.join(__addon__.getAddonInfo('path'), 'resources/art/') + 'trans_checked.png'

        self.ctrlBackground = xbmcgui.ControlImage(0, 0, 1280, 720, bg_image)
        self.cancelled = False
        self.addControl(self.ctrlBackground)

        self.strActionInfo = xbmcgui.ControlLabel(250, 20, 724, 400, 'Veuillez sélectionnez les images correspondants au thème.\nIl devrait y en avoir 3 ou 4 à sélectionner.', 'font40', '0xFFFF00FF')
        self.addControl(self.strActionInfo)

        self.msg = kwargs.get('msg')
        self.roundnum = kwargs.get('roundnum')
        self.strActionInfo = xbmcgui.ControlLabel(250, 70, 700, 300, 'Le thème est: ' + self.msg, 'font13', '0xFFFF00FF')
        self.addControl(self.strActionInfo)

        self.addControl(self.img)

        self.chk = [0]*9
        self.chkbutton = [0]*9
        self.chkstate = [False]*9

        if 1 == 2:
            self.chk[0] = xbmcgui.ControlCheckMark(250, 110, 260, 166, '1', font='font14', focusTexture=check_image, checkWidth=260, checkHeight=166)
            self.chk[1] = xbmcgui.ControlCheckMark(250 + 260, 110, 260, 166, '2', font='font14', focusTexture=check_image, checkWidth=260, checkHeight=166)
            self.chk[2] = xbmcgui.ControlCheckMark(250 + 520, 110, 260, 166, '3', font='font14', focusTexture=check_image, checkWidth=260, checkHeight=166)

            self.chk[3] = xbmcgui.ControlCheckMark(250, 110 + 166, 260, 166, '4', font='font14', focusTexture=check_image, checkWidth=260, checkHeight=166)
            self.chk[4] = xbmcgui.ControlCheckMark(250 + 260, 110 + 166, 260, 166, '5', font='font14', focusTexture=check_image, checkWidth=260, checkHeight=166)
            self.chk[5] = xbmcgui.ControlCheckMark(250 + 520, 110 + 166, 260, 166, '6', font='font14', focusTexture=check_image, checkWidth=260, checkHeight=166)

            self.chk[6] = xbmcgui.ControlCheckMark(250, 110 + 332, 260, 166, '7', font='font14', focusTexture=check_image, checkWidth=260, checkHeight=166)
            self.chk[7] = xbmcgui.ControlCheckMark(250 + 260, 110 + 332, 260, 166, '8', font='font14', focusTexture=check_image, checkWidth=260, checkHeight=166)
            self.chk[8] = xbmcgui.ControlCheckMark(250 + 520, 110 + 332, 260, 166, '9', font='font14', focusTexture=check_image, checkWidth=260, checkHeight=166)

        else:
            self.chk[0] = xbmcgui.ControlImage(250, 110, 260, 166, check_image)
            self.chk[1] = xbmcgui.ControlImage(250 + 260, 110, 260, 166, check_image)
            self.chk[2] = xbmcgui.ControlImage(250 + 520, 110, 260, 166, check_image)

            self.chk[3] = xbmcgui.ControlImage(250, 110 + 166, 260, 166, check_image)
            self.chk[4] = xbmcgui.ControlImage(250 + 260, 110 + 166, 260, 166, check_image)
            self.chk[5] = xbmcgui.ControlImage(250 + 520, 110 + 166, 260, 166, check_image)

            self.chk[6] = xbmcgui.ControlImage(250, 110 + 332, 260, 166, check_image)
            self.chk[7] = xbmcgui.ControlImage(250 + 260, 110 + 332, 260, 166, check_image)
            self.chk[8] = xbmcgui.ControlImage(250 + 520, 110 + 332, 260, 166, check_image)

            self.chkbutton[0] = xbmcgui.ControlButton(250, 110, 260, 166, '1', font='font1')
            self.chkbutton[1] = xbmcgui.ControlButton(250 + 260, 110, 260, 166, '2', font='font1')
            self.chkbutton[2] = xbmcgui.ControlButton(250 + 520, 110, 260, 166, '3', font='font1')

            self.chkbutton[3] = xbmcgui.ControlButton(250, 110 + 166, 260, 166, '4', font='font1')
            self.chkbutton[4] = xbmcgui.ControlButton(250 + 260, 110 + 166, 260, 166, '5', font='font1')
            self.chkbutton[5] = xbmcgui.ControlButton(250 + 520, 110 + 166, 260, 166, '6', font='font1')

            self.chkbutton[6] = xbmcgui.ControlButton(250, 110 + 332, 260, 166, '7', font='font1')
            self.chkbutton[7] = xbmcgui.ControlButton(250 + 260, 110 + 332, 260, 166, '8', font='font1')
            self.chkbutton[8] = xbmcgui.ControlButton(250 + 520, 110 + 332, 260, 166, '9', font='font1')

        for obj in self.chk:
            self.addControl(obj)
            obj.setVisible(False)
        for obj in self.chkbutton:
            self.addControl(obj)

        self.cancelbutton = xbmcgui.ControlButton(250 + 260 - 70, 620, 140, 50, 'Cancel', alignment=2)
        self.okbutton = xbmcgui.ControlButton(250 + 520 - 50, 620, 100, 50, 'OK', alignment=2)
        self.addControl(self.okbutton)
        self.addControl(self.cancelbutton)

        self.chkbutton[6].controlDown(self.cancelbutton);  self.chkbutton[6].controlUp(self.chkbutton[3])
        self.chkbutton[7].controlDown(self.cancelbutton);  self.chkbutton[7].controlUp(self.chkbutton[4])
        self.chkbutton[8].controlDown(self.okbutton);      self.chkbutton[8].controlUp(self.chkbutton[5])

        self.chkbutton[6].controlLeft(self.chkbutton[8]);  self.chkbutton[6].controlRight(self.chkbutton[7]);
        self.chkbutton[7].controlLeft(self.chkbutton[6]);  self.chkbutton[7].controlRight(self.chkbutton[8]);
        self.chkbutton[8].controlLeft(self.chkbutton[7]);  self.chkbutton[8].controlRight(self.chkbutton[6]);

        self.chkbutton[3].controlDown(self.chkbutton[6]);  self.chkbutton[3].controlUp(self.chkbutton[0])
        self.chkbutton[4].controlDown(self.chkbutton[7]);  self.chkbutton[4].controlUp(self.chkbutton[1])
        self.chkbutton[5].controlDown(self.chkbutton[8]);  self.chkbutton[5].controlUp(self.chkbutton[2])

        self.chkbutton[3].controlLeft(self.chkbutton[5]);  self.chkbutton[3].controlRight(self.chkbutton[4]);
        self.chkbutton[4].controlLeft(self.chkbutton[3]);  self.chkbutton[4].controlRight(self.chkbutton[5]);
        self.chkbutton[5].controlLeft(self.chkbutton[4]);  self.chkbutton[5].controlRight(self.chkbutton[3]);

        self.chkbutton[0].controlDown(self.chkbutton[3]);  self.chkbutton[0].controlUp(self.cancelbutton)
        self.chkbutton[1].controlDown(self.chkbutton[4]);  self.chkbutton[1].controlUp(self.cancelbutton)
        self.chkbutton[2].controlDown(self.chkbutton[5]);  self.chkbutton[2].controlUp(self.okbutton)

        self.chkbutton[0].controlLeft(self.chkbutton[2]);  self.chkbutton[0].controlRight(self.chkbutton[1]);
        self.chkbutton[1].controlLeft(self.chkbutton[0]);  self.chkbutton[1].controlRight(self.chkbutton[2]);
        self.chkbutton[2].controlLeft(self.chkbutton[1]);  self.chkbutton[2].controlRight(self.chkbutton[0]);

        self.cancelled = False
        self.setFocus(self.okbutton)
        self.okbutton.controlLeft(self.cancelbutton);      self.okbutton.controlRight(self.cancelbutton);
        self.cancelbutton.controlLeft(self.okbutton);      self.cancelbutton.controlRight(self.okbutton);
        self.okbutton.controlDown(self.chkbutton[2]);      self.okbutton.controlUp(self.chkbutton[8]);
        self.cancelbutton.controlDown(self.chkbutton[0]);  self.cancelbutton.controlUp(self.chkbutton[6]);

    def get(self):
        self.doModal()
        self.close()
        if not self.cancelled:
            retval = ""
            for objn in range(9):
                if self.chkstate[objn]:
                    retval += ("" if retval == "" else ",") + str(objn)
            return retval

        else:
            return ""

    def anythingChecked(self):
        for obj in self.chkstate:
            if obj:
                return True
        return False

    def onControl(self, control):
        if str(control.getLabel()) == "OK":
            if self.anythingChecked():
                self.close()
        elif str(control.getLabel()) == "Cancel":
            self.cancelled = True
            self.close()
        try:
            if 'xbmcgui.ControlButton' in repr(type(control)):
                index = control.getLabel()
                if index.isnumeric():
                    self.chkstate[int(index)-1] = not self.chkstate[int(index)-1]
                    self.chk[int(index)-1].setVisible(self.chkstate[int(index)-1])

        except:
            pass

    def onAction(self, action):
        if action == 10:
            self.cancelled = True
            self.close()


def ResolveCaptcha(key, urlOuo):
    urlBase = 'https://www.google.com/recaptcha/api/fallback?k=' + key
    oRequestHandler = cRequestHandler(urlBase)
    oRequestHandler.addHeaderEntry('User-Agent', UA)
    oRequestHandler.addHeaderEntry('Accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8')
    oRequestHandler.addHeaderEntry('Accept-Language', 'fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3')
    oRequestHandler.addHeaderEntry('Accept-Encoding', 'gzip, deflate')
    oRequestHandler.addHeaderEntry('Referer', urlOuo)
    body = oRequestHandler.request()

    captchaScrap = re.findall('value="8"><img class="fbc-imageselect-payload" src="(.+?)"', str(body))

    text = re.search('<div class="rc-imageselect.+?">.+?<strong>(.+?)</strong>', str(body)).group(1)

    c = re.search('method="POST"><input type="hidden" name="c" value="(.+?)"', str(body)).group(1)
    k = re.search('k=(.+?)" alt=', str(body)).group(1)
    params = {"c": c, "k": k}
    query_string = urlEncode(params)

    url = 'https://www.google.com' + str(captchaScrap[0]) + '?' + query_string

    filePath = 'special://home/userdata/addon_data/plugin.video.matrix/Captcha.raw'

    oRequestHandler = cRequestHandler(url)
    htmlcontent = oRequestHandler.request()

    downloaded_image = xbmcvfs.File(filePath, 'wb')
    downloaded_image.write(htmlcontent)
    downloaded_image.close()

    oSolver = cInputWindow(captcha=filePath, msg=text, roundnum=1)
    retArg = oSolver.get()

    allNumber = [int(s) for s in re.findall('([0-9])', str(retArg))]
    responseFinal = ""
    for rep in allNumber:
        responseFinal = responseFinal + '&response=' + str(rep)

    headers = {'User-Agent': UA,
               'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
               'Accept-Language': 'fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3',
               'Accept-Encoding': 'gzip, deflate',
               'Referer': url,
               'Content-Type': 'application/x-www-form-urlencoded',
               'Content-Length': str(len(params))}

    params = 'c=' + c + responseFinal

    oRequestHandler = cRequestHandler(urlBase)
    oRequestHandler.setRequestType(1)
    oRequestHandler.addHeaderEntry('User-Agent', UA)
    oRequestHandler.addHeaderEntry('Accept', 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8')
    oRequestHandler.addHeaderEntry('Accept-Language', 'fr,fr-FR;q=0.8,en-US;q=0.5,en;q=0.3')
    oRequestHandler.addHeaderEntry('Accept-Encoding', 'gzip, deflate')
    oRequestHandler.addHeaderEntry('Referer', url)
    oRequestHandler.addHeaderEntry('Content-Type', 'application/x-www-form-urlencoded')
    oRequestHandler.addHeaderEntry('Content-Length', str(len(params)))
    oRequestHandler.addParametersLine(params)

    sHtmlContent = oRequestHandler.request()

    token = re.search('<textarea dir="ltr" readonly>(.+?)<', sHtmlContent).group(1)
    if not token:
        dialogs = dialog()
        dialogs.VSinfo("Captcha non valide")
    return token


def getUrl(url, cookieJar=None, post=None, timeout=20, headers=None, noredir=False):

    cookie_handler = urllib2.HTTPCookieProcessor(cookieJar)

    if noredir:
        opener = urllib2.build_opener(Noredirection, cookie_handler, urllib2.HTTPBasicAuthHandler(), urllib2.HTTPHandler())
    else:
        opener = urllib2.build_opener(cookie_handler, urllib2.HTTPBasicAuthHandler(), urllib2.HTTPHandler())
    # opener = urllib2.install_opener(opener)
    req = urllib2.Request(url)

    if headers:
        for h, hv in headers:
            req.add_header(h, hv)
    else:
        req.add_header('User-Agent', 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/33.0.1750.154 Safari/537.36')
        req.add_header('Accept-Language', __sLang__)

    VSlog('post : ' + str(post))
    response = opener.open(req, post, timeout=timeout)
    link = response.read()
    response.close()
    return link


class UnCaptchaReCaptcha:

    def _collect_api_info(self):

        html = getUrl("http://www.google.com/recaptcha/api.js")
        a = re.search(r'po.src = \'(.*?)\';', html).group(1)
        vers = a.split("/")[5]

        questionfile = a
        VSlog("Fichier questions: %s" % questionfile)
        VSlog("API version: %s" % vers)

        language = a.split("__")[1].split(".")[0]
        VSlog("API language: %s" % language)

        html = getUrl("https://apis.google.com/js/api.js")
        b = re.search(r'"h":"(.*?)","', html).group(1)
        jsh = b.decode('unicode-escape')

        VSlog("API jsh-string: %s" % jsh)
        return vers, language, jsh, questionfile

    def _prepare_time_and_rpc(self):
        # getUrl("http://www.google.com/recaptcha/api2/demo")
        millis = int(round(time.time() * 1000))
        VSlog("Time: %s" % millis)

        rand = random.randint(1, 99999999)
        a = "0.%s" % str(rand * 2147483647)
        rpc = int(100000000 * float(a))

        VSlog("Rpc-token: %s" % rpc)
        return millis, rpc

    def ExtReg(self, r, chain):
        r = re.search(r, chain)
        if not r:
            return ''
        return r.group(1)

    def processCaptcha(self, key, lang, gcookieJar):
        headers = [("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:37.0) Gecko/20100101 Firefox/37.0"),
                   # ("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"),
                   ("Referer", "https://www.google.com/recaptcha/api2/demo"),
                   ("Accept-Language", lang)]

        millis, rpc = self._prepare_time_and_rpc()
        co = base64.b64encode('https://www.google.com:443')
        botguardstring = "!A"
        vers, language, jsh, questionfile = self._collect_api_info()

        post_data = None
        token = ''
        iteration = 0
        reCaptchaUrl = 'http://www.google.com/recaptcha/api/fallback?k=%s' % key

        while iteration < 20:

            millis_captcha_loading = int(round(time.time() * 1000))

            # ,'cookiefile':self.COOKIE_FILE, 'use_cookie': True, 'load_cookie': True, 'save_cookie': True
            data = getUrl(reCaptchaUrl, headers=headers, post=post_data, cookieJar=gcookieJar)
            VSlog(reCaptchaUrl)
            imgUrl = re.search(r'"(/recaptcha/api2/payload[^"]+?)"', data).group(1)

            VSlog(imgUrl)
            iteration += 1
            message = self.ExtReg(r'<label[^>]+class="fbc-imageselect-message-text"[^>]*>(.*?)</label>', data)

            if '' == message:
                message = self.ExtReg(r'<div[^>]+class="fbc-imageselect-message-error">(.*?)</div>', data)
            if '' == message:
                token = re.search(r'"this\.select\(\)">(.*?)</textarea>', data).group(1)
                if '' != token:
                    VSlog('>>>>>>>> Captcha token[%s]' % token)
                else:
                    VSlog('>>>>>>>> Captcha Failed')
                break

            cval = re.search(r'name="c"\s+value="([^"]+)', data).group(1)
            imgUrl = 'https://www.google.com%s' % (imgUrl.replace('&amp;', '&'))
            accepLabel = re.search(r'type="submit"\s+value="([^"]+)', data).group(1)

            filePath = 'c://c.jpeg'
            import random
            n = random.randint(1, 1000)
            filePath = 'c://c' + str(n) + '.jpeg'

            VSlog(">>>>>>>> Captcha message[%s]" % message)
            VSlog(">>>>>>>> Captcha accep label[%s]" % accepLabel)
            VSlog(">>>>>>>> Captcha imgUrl[%s] filePath[%s]" % (imgUrl, filePath))

            # params = {'maintype': 'image', 'subtypes':['jpeg'], 'check_first_bytes':['\xFF\xD8', '\xFF\xD9']}
            # ret = self.cm.saveWebFile(filePath, imgUrl, params)
            # retArg = self.sessionEx.waitForFinishOpen(UnCaptchaReCaptchaWidget, imgFilePath=filePath, message=message, title="reCAPTCHA v2", additionalParams={'accep_label':accepLabel})

            ret = ''
            ret = getUrl(imgUrl, headers=headers, cookieJar=gcookieJar)
            downloaded_image = file(filePath, 'wb')
            downloaded_image.write(ret)
            downloaded_image.close()

            oSolver = cInputWindow(captcha=filePath, msg=message, roundnum=iteration)
            retArg = oSolver.get()
            VSlog('>>>>>>>> Captcha response [%s]' % retArg)

            responses = base64.b64encode('{"response":[%s]}' % retArg)
            # VSlog(responses)
            responses=responses.replace('=', '.')

            if retArg is not None and len(retArg) and retArg[0]:
                post_data = urlEncode({'c': cval, 'response': responses}, doseq=True)
            else:
                break

            if False:
                timeToSolve = int(round(time.time() * 1000)) - millis_captcha_loading
                timeToSolveMore = timeToSolve  # timeToSolve + int(float("0." + str(random.randint(1, 99999999))) * 500)

                postdata = urlEncode({'c': cval, 'response': responses, 'v': vers,
                                      't': timeToSolve, 'bg': botguardstring, 'ct': timeToSolveMore})
                html = getUrl('https://www.google.com/recaptcha/api2/userverify?k=' + key, post=postdata, headers=headers)
                # fh = open('c:\\test.txt', 'w')
                # fh.write(html)
                # fh.close()

        return token


def getg():
    return None
    cookieJar = cookielib.LWPCookieJar()
    try:
        cookieJar.load("./gsite.jwl")
    except:
        pass


def performCaptcha(sitename, cj, returnpage=True, captcharegex='data-sitekey="(.*?)"', lang="fr", headers=None):
    gcookieJar = getg()
    sitepage = getUrl(sitename, cookieJar=cj, headers=headers)
    sitekey = re.findall(captcharegex, sitepage)
    token = ""
    if len(sitekey) >= 1:
        # getUrl('https://www.google.com/', cookieJar=gcookieJar)
        c = UnCaptchaReCaptcha()
        token = c.processCaptcha(sitekey[0], lang, gcookieJar)
        if returnpage:
            # gcookieJar.save('./gsite.jwl');
            headers = [("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:37.0) Gecko/20100101 Firefox/37.0"),
                       ("Referer", sitename)]
            sitepage = getUrl(sitename, cookieJar=cj, post=urlEncode({"g-recaptcha-response": token}), headers=headers)

    if returnpage:
        # fh = open('c:\\reussi.txt', 'w')
        # fh.write(sitepage)
        # fh.close()
        return sitepage
    else:
        return token

# performCaptcha("http://www.livetv.tn/", cookieJar)
