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

import re

from ..internal.CaptchaService import CaptchaService

class CoinHive(CaptchaService):
    __name__ = 'CoinHive'
    __type__ = 'captcha'
    __version__ = '0.01'
    __status__ = 'testing'

    __description__ = 'CoinHive captcha service plugin'
    __license__ = 'GPLv3'
    __authors__ = [("GammaC0de", "nitzo2001[AT]yahoo[DOT]com")]

    KEY_PATTERN = r'class=[\'"]coinhive-captcha[\'"].+?data-key\s*=[\'"](\w+?)[\'"]'
    HASHES_PATTERN = r'class=[\'"]coinhive-captcha[\'"].+?data-hashes\s*=[\'"](\d+?)[\'"]'

    COINHIVE_INTERACTIVE_SIG = "792398cf130e9cb0d1c16363c87122a623d0bc7410bd981000f5cbfe1c6ec6708d16edf19bc2703b" + \
                               "04291697cfde5194c5dc290a23b10af5ad6a26606867a5e38031aa24d715c7ec48a5c61272d757a5" + \
                               "4835e77558933744a3f0ad245a72ea9447893284c4fd458544a9bff09c19b187321ec7b0f1b2b21e" + \
                               "246bef741b27f3058b2467a192c100b78bb311300e5da0ce95b331bb77215e261fb4a6b78acd89a7" + \
                               "13aefdc393fb19f3cdb4682b084c5747347f344fd49ed86bad7fba1ad2f059663ff1b800cffa8948" + \
                               "bb9c12dddf0ae96831b85c4f9526460cd2a4355c4f800aeb4b541b5c5bee62dc5bfb18c6656c0304" + \
                               "0b2a819edd07480911b6dadf430f6eb1"

    COINHIVE_INTERACTIVE_JS = """
            while(document.children[0].childElementCount > 0) {
                document.children[0].removeChild(document.children[0].children[0]);
            }
            document.children[0].innerHTML = '<html><body><div class="coinhive-captcha"' + (request.params.hashes ? 'data-hashes="' + request.params.hashes +'"' : '') + ' data-key="' + request.params.key +'" data-callback="pyloadCaptchaFinishCallback"><em>Loading Coinhive Captcha...</em></div></body></html>';

            gpyload.getFrameSize = function() {
                var divCoinHive = document.body.querySelector("iframe[src*='authedmine.com/captcha/']");
                if (divCoinHive !== null) {
                    var rect = divCoinHive.getBoundingClientRect();
                    return {top: Math.round(rect.top), right: Math.round(rect.right), bottom: Math.round(rect.bottom), left: Math.round(rect.left)};
                } else {
                    return {top: 0, right: 0, bottom: 0, left: 0};
                };
            };
            window.pyloadCaptchaFinishCallback = function(token){
                gpyload.submitResponse(token);
            }
            var js_script = document.createElement('script');
            js_script.type = "text/javascript";
            js_script.src = "https://authedmine.com/lib/captcha.min.js";
            js_script.async = true;
            document.getElementsByTagName('head')[0].appendChild(js_script);

            gpyload.activated();"""

    def detect_key(self, data=None):
        html = data or self.retrieve_data()

        m = re.search(self.KEY_PATTERN, html)
        if m is not None:
            self.key = m.group(1).strip()
            self.log_debug("Key: %s" % self.key)
            return self.key
        else:
            self.log_warning(_("Key pattern not found"))
            return None

    def detect_hashes(self, data=None):
        html = data or self.retrieve_data()
        m = re.search(self.HASHES_PATTERN, html)
        if m is not None:
            self.hashes = m.group(1).strip()
            self.log_debug("Hashes: %s" % self.hashes)
            return self.hashes
        else:
            self.log_warning(_("Hashes pattern not found"))
            return None

    def challenge(self, key=None, hashes=None, data=None):
        key = key or self.retrieve_key(data)
        hashes = hashes or self.detect_hashes(data)
        params = {'url': self.pyfile.url,
                  'key': key,
                  'hashes': hashes,
                  'script': {'signature': self.COINHIVE_INTERACTIVE_SIG,
                             'code': self.COINHIVE_INTERACTIVE_JS}}

        result = self.decrypt_interactive(params, timeout=300)

        return result

if __name__ == "__main__":
    # Sign with the command `python -m module.plugins.captcha.CoinHive pyload.private.pem pem_passphrase`
    import sys
    from ..internal.misc import sign_string

    if len(sys.argv) > 2:
        with open(sys.argv[1], 'r') as f:
            pem_private = f.read()

        print sign_string(CoinHive.COINHIVE_INTERACTIVE_JS, pem_private, pem_passphrase=sys.argv[2], sign_algo="SHA384")
