# -*- coding:utf-8 -*-
import re
import os
import sys
import random
import logging
import requests
import traceback

from functools import partial
from argparse import ArgumentParser
from googletrans.gtoken import TokenAcquirer

from . import sites
from .tools import retry_wrapper


__version__ = "1.1.5"


class Translate(object):
    """
        翻译类
    """
    proxy_list = [None]
    headers = {
        'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_2) AppleWebKit/537.36 (KHTML, like Gecko)'
                      ' Chrome/41.0.2272.76 Safari/537.36',
        'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
        "Accept-Language": "en-US,en;q=0.5",
    }

    def __init__(self, web_site=None, proxy_list=None, proxy_auth=None,
                 retry_times=10, translate_timeout=5, load_module=None):
        if web_site:
            self.web_site = web_site.split(",")
        self.proxy = {}
        self.proxy_auth = proxy_auth
        self.retry_times = retry_times
        self.translate_timeout = translate_timeout

        if proxy_list and os.path.exists(proxy_list):
            self.proxy_list = [i.strip() for i in open(proxy_list).readlines() if (i.strip() and i.strip()[0] != "#")]
        self.load(sites)
        if load_module:
            self.load(load_module)

    def __enter__(self):
        self.session = requests.Session()
        self.acquirer = TokenAcquirer(session=self.session)
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.session.close()

    def set_logger(self, logger=None):
        if not logger:
            self.logger = logging.getLogger()
            self.logger.setLevel(20)
            self.logger.addHandler(logging.StreamHandler(sys.stdout))
        else:
            self.logger = logger
            self.name = logger.name

    def load(self, module_str):
        if isinstance(module_str, str):
            sys.path.insert(0, os.getcwd())
            model = __import__(module_str, fromlist=module_str.split(".")[-1])
        else:
            model = module_str

        for k in dir(model):
            v = getattr(model, k)
            if hasattr(v, "__call__"):
                self.__dict__[k] = partial(v, self)

    def proxy_choice(self):
        return self.proxy_list and self.proxy_list[0] and {"http": "http://%s%s"%(
            "%s@"%self.proxy_auth if self.proxy_auth else "", random.choice(self.proxy_list))}

    def trans_error_handler(self, func_name, retry_time, e, *args, **kwargs):
        """
        error_handler实现参数
        :param func_name: 重试函数的名字
        :param retry_time: 重试到了第几次
        :param e: 需要重试的异常
        :param args: 重试参数的参数
        :param kwargs: 重试参数的参数
        :return: 当返回True时，该异常不会计入重试次数
        """
        self.logger.debug("Error in %s for retry %s times. Error: %s"%(func_name, retry_time, e))
        args[1].update(self.proxy_choice())

    def translate(self, src):
        """
        翻译主函数
        :param src: 源
        :return: 结果
        """
        try:
            # 找出大于号和小于号之间的字符，使用换行符连接，进行翻译
            pattern = re.compile(r"(?:^|(?<=>))([\s\S]*?)(?:(?=<)|$)")
            ls = re.findall(pattern, src.replace("\n", ""))
            src_data = "\n".join(x.strip("\t ") for x in ls if x.strip())
            if src_data.strip():
                # 对源中的%号进行转义
                src_escape = src.replace("%", "%%")
                # 将源中被抽离进行翻译的部分替换成`%s`， 如果被抽离部分没有实质内容（为空），则省略
                src_template = re.sub(pattern, lambda x: "%s" if x.group(1).strip() else "", src_escape)
                return retry_wrapper(self.retry_times, self.trans_error_handler)(
                    self._translate)(src_data, self.proxy or self.proxy_choice()
                                     or self.proxy, src_template)
        except Exception:
            self.logger.error("Error in translate, finally, we could not get the translate result. src: %s, Error:  %s"%(
                src, traceback.format_exc()))
        return src

    def _translate(self, src, proxies, src_template):
        return getattr(self, random.choice(self.web_site).strip())(src, proxies, src_template)


def main():
    parser = ArgumentParser()
    parser.add_argument("-ws", "--web-site", default="baidu,qq,google",
                        help="Which site do you want to use for translating, split by `,`?")
    parser.add_argument("-pl", "--proxy-list",
                        help="The proxy.list contains proxy to use for translating. default: ./proxy.list")
    parser.add_argument("-pa", "--proxy-auth",
                        help="Proxy password if have. eg. user:password")
    parser.add_argument("-rt", "--retry-times", type=int, default=10,
                        help="If translate failed retry times. default: 10")
    parser.add_argument("-tt", "--translate-timeout", type=int, default=5, help="Translate timeout. default: 5")
    parser.add_argument("-lm", "--load-module",
                        help="The module contains custom web site functions which may use for translate. eg: trans.qq")
    parser.add_argument("src", nargs="+", help="The html you want to translate. ")
    data = vars(parser.parse_args())
    src = data.pop("src")
    with Translate(**dict(filter(lambda x: x[1], data.items()))) as translator:
        translator.set_logger()
        print(translator.translate(" ".join(src)))


if __name__ == "__main__":
    main()
