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

from __future__ import with_statement

import re

from base64 import b64encode
from thread import start_new_thread
from time import sleep

from module.network.HTTPRequest import BadHeader
from module.network.RequestFactory import getURL

from module.plugins.Hook import Hook


class Captcha9kw(Hook):
    __name__    = "Captcha9kw"
    __type__    = "hook"
    __version__ = "0.15"

    __config__ = [("activated", "bool", "Activated", True),
                  ("force", "bool", "Force captcha resolving even if client is connected", True),
                  ("confirm", "bool", "Confirm Captcha (Cost +6)", False),
                  ("captchaperhour", "int", "Captcha per hour", "9999"),
                  ("prio", "int", "Priority (max. 20)(Cost +0 -> +20)", "0"),
                  ("queue", "int", "Max. Queue (max. 999)", "0"),
                  ("hoster_options", "string", "Hoster options (Format: pluginname:prio=1:selfsolfe=1:confirm=1:timeout=900;)", "ShareonlineBiz:prio=0:timeout=999;UploadedTo:prio=0:timeout=999;SerienjunkiesOrg:prio=1:min=3;max=3;timeout=90"),
                  ("selfsolve", "bool", "If enabled and you have a 9kw client active only you will get your captcha to solve it (Selfsolve)", "0"),
                  ("passkey", "password", "API key", ""),
                  ("timeout", "int", "Timeout (min. 60s, max. 3999s)", "900")]

    __description__ = """Send captchas to 9kw.eu"""
    __license__     = "GPLv3"
    __authors__     = [("RaNaN", "RaNaN@pyload.org"),
                       ("Walter Purcaro", "vuolter@gmail.com")]


    API_URL = "http://www.9kw.eu/index.cgi"


    def setup(self):
        self.info = {}  #@TODO: Remove in 0.4.10


    def getCredits(self):
        res = getURL(self.API_URL,
                     get={'apikey': self.getConfig("passkey"),
                          'pyload': "1",
                          'source': "pyload",
                          'action': "usercaptchaguthaben"})

        if res.isdigit():
            self.logInfo(_("%d credits left") % res)
            credits = self.info["credits"] = int(res)
            return credits
        else:
            self.logError(res)
            return 0


    def _processCaptcha(self, task):
        try:
            with open(task.captchaFile, 'rb') as f:
                data = f.read()
        except IOError, e:
            self.logError(e)
            return

        data = b64encode(data)
        mouse = 1 if task.isPositional() else 0
        pluginname = re.search(r'_([^_]*)_\d+.\w+', task.captchaFile).group(1)

        self.logDebug("%s: %s" % (task.captchaFile, data))

        option = {'min'            : 2,
                  'max'            : 50,
                  'phrase'         : 0,
                  'numeric'        : 0,
                  'case_sensitive' : 0,
                  'math'           : 0,
                  'prio'           : self.getConfig("prio"),
                  'confirm'        : self.getConfig("confirm"),
                  'timeout'        : min(max(self.getConfig("timeout") * 60, 300), 3999),
                  'selfsolve'      : self.getConfig("selfsolve"),
                  'cph'            : self.getConfig("captchaperhour"),
                  'hoster_options' : self.getConfig("hoster_options").split(";")}

        for opt in hoster_options:
            details = opt.split(":")

            if not details or details[0].lower() != pluginname.lower():
                continue

            for d in details:
                hosteroption = d.split("=")

                if len(hosteroption) <= 1 or not hosteroption[1].isdigit():
                    continue

                o = hosteroption[0].lower()
                if o in option:
                    option[o] = hosteroption[1]

        for _ in xrange(5):
            post_data = {'apikey'        : self.getConfig("passkey"),
                         'prio'          : prio_option,
                         'confirm'       : confirm_option,
                         'maxtimeout'    : timeout_option,
                         'selfsolve'     : selfsolve_option,
                         'captchaperhour': cph_option,
                         'case-sensitive': case_sensitive_option,
                         'min_len'       : min_option,
                         'max_len'       : max_option,
                         'phrase'        : phrase_option,
                         'numeric'       : numeric_option,
                         'math'          : math_option,
                         'oldsource'     : pluginname,
                         'pyload'        : "1",
                         'source'        : "pyload",
                         'base64'        : "1",
                         'mouse'         : mouse,
                         'file-upload-01': data,
                         'action'        : "usercaptchaupload"}
            try:
                res = getURL(self.API_URL, post=post_data)
                if res:
                    break
            except BadHeader, e:
                sleep(3)

        if not res.isdigit():
            self.logError(_("Bad upload: %s") % res)
            return

        self.logInfo(_("NewCaptchaID from upload: %s : %s") % (res, task.captchaFile))

        task.data["ticket"] = res
        self.logInfo("result %s : %s" % (res, result))

        for _ in xrange(int(self.getConfig("timeout") / 5)):
            res2 = getURL(self.API_URL,
                          get={'apikey': self.getConfig("passkey"),
                               'id'    : res,
                               'pyload': "1",
                               'info'  : "1",
                               'source': "pyload",
                               'action': "usercaptchacorrectdata"})

            if not res2 or res2 == "NO DATA":
                sleep(5)
            else:
                break

        task.setResult(res2 or None)


    def newCaptchaTask(self, task):
        if not task.isTextual() and not task.isPositional():
            return

        elif not self.getConfig("passkey"):
            return

        elif self.core.isClientConnected() and not self.getConfig("force"):
            return

        credits = self.getCredits()

        if not credits:
            self.logError(_("Your Captcha 9kw.eu Account has not enough credits"))
            return

        queue = self.getConfig("queue")
        timeout = min(max(self.getConfig("timeout") * 60, 300), 3999)
        hoster_options = self.getConfig("hoster_options").split(";")
        pluginname = re.search(r'_([^_]*)_\d+.\w+', task.captchaFile).group(1)

        if 1000 > queue > 10:
            servercheck = getURL("http://www.9kw.eu/grafik/servercheck.txt")
            regex = re.compile("queue=(\d+)")

            for _ in xrange(3):
                if queue < regex.search(servercheck).group(1):
                    break

                sleep(10)

        for opt in hoster_options:
            details = opt.split(":")

            if not details or details[0].lower() != pluginname.lower():
                continue

            for d in details:
                hosteroption = d.split("=")

                if (len(hosteroption) > 1
                    and hosteroption[0].lower() == 'timeout'
                    and hosteroption[1].isdigit()):
                    timeout = int(hosteroption[1])

        task.handler.append(self)

        task.setWaiting(timeout)

        start_new_thread(self._processCaptcha, (task,))


    def _captchaResponse(self, task, correct):
        if "ticket" not in task.data:
            self.logDebug(_("No CaptchaID for %s request (task: %s)" % type) % task)
            return

        type = "correct" if correct else "refund"
        passkey = self.getConfig("passkey")

        for _ in xrange(3):
            res = getURL(self.API_URL,
                         get={'action' : "usercaptchacorrectback",
                              'apikey' : passkey,
                              'api_key': passkey,
                              'correct': "1" if correct else "2",
                              'pyload' : "1",
                              'source' : "pyload",
                              'id'     : task.data["ticket"]})

            if res is "OK":
                self.logInfo(_("Request %s: %s" % type) % res)
                return
            else:
                self.logDebug(_("Could not send %s request: %s" % type) % res)
                sleep(1)


    def captchaCorrect(self, task):
        self._captchaResponse(self, task, True)


    def captchaInvalid(self, task):
        self._captchaResponse(self, task, False)