# -*- coding: UTF-8 -*-
import os
import re

from django.conf import settings
from gm_upload.utils.qiniu_tool import QiniuTool
from qiniu import put_file

from utils.logger import log_error, info_logger


class QiniuFileTool(QiniuTool):
    @classmethod
    def upload_file(cls, file_path, save_name, bucket_name):
        """
        上传文件到七牛
        :param file_path: 文本路径
        :param save_name: 上传的名字
        :param bucket_name: 空间名
        :return:
        """
        token = cls.q.upload_token(bucket_name)

        for _ in range(5):  # 多次尝试
            ret, response_info = put_file(token, save_name, file_path)

            if ret and "key" in ret and response_info.status_code == 200:
                # assert ret["key"] == save_name
                # assert ret["hash"] == etag(file_path)

                return {
                    "file": ret["key"]
                }

        raise Exception('upload filed')


class ChannelPackage(object):
    # 渠道识别前缀
    channel_prefix = 'gm_alpha'

    def __init__(self, api_data, version):
        self.apk_data = api_data
        self.version = version
        self.apk = None

    @classmethod
    def get_parent_path(cls, data):  # 母包地址
        path = os.getcwd() + '/' + cls.channel_prefix + '.apk'
        with open(path, 'wb')as fw:
            fw.write(data)
        return path

    def build_channel_apk(self, channel_name):
        cp = re.compile(r'[^{}]+')
        self.apk = self.channel_prefix + '.apk'
        walle_cli_path = os.getcwd() + '/walle-cli-all.jar'
        with open(self.apk, 'wb') as fw:
            fw.write(self.apk_data)
        os.system('java -jar {0} batch -c {1} {2}'.format(walle_cli_path, channel_name, self.apk))
        targe_apk = self.channel_prefix + '_' + channel_name + '.apk'
        cmd_res = os.popen('java -jar walle-cli-all.jar show %s' % targe_apk)
        ret_res = cmd_res.readlines()[0]
        target_channel_info = cp.findall(ret_res)[1]
        if target_channel_info and channel_name == target_channel_info.split('=')[1]:
            os.remove(self.apk)
            return targe_apk
        else:
            log_error()
        os.remove(self.apk)
        os.remove(self.channel_prefix + '_' + channel_name + '.apk')

    def upload_apk(self, channel_name):
        chn_apk_path = self.build_channel_apk(channel_name)
        apk_uri = self.apk_key(channel_name, self.version)
        QiniuTool.delete(apk_uri, settings.APK_SCOPE)
        ret = QiniuFileTool.upload_file(chn_apk_path, apk_uri, settings.APK_SCOPE)
        res_resp = QiniuTool.refresh(['http://alpha-s.iyanzhi.com/' + apk_uri])
        info_logger.debug(res_resp)
        os.remove(chn_apk_path)
        return ret

    @classmethod
    def apk_key(cls, channel, version):
        build_dir = getattr(settings, 'APK_BUILD_DIR', '')
        if channel:
            uri = '{version}/{channel}/gm_alpha_{channel}.apk'.format(version=version, channel=channel)
        else:
            uri = '{version}/gm_alpha.apk'.format(version=version)
        if build_dir:
            uri = '{build_dir}/{uri}'.format(build_dir=build_dir, uri=uri)
        return uri

    @classmethod
    def apk_url(cls, channel, version):
        key = cls.apk_key(channel, version)
        url = settings.APK_DOMAIN + key
        return url

    @classmethod
    def publish_apk(cls, channel, version, need_refresh=True):
        apk_scope = settings.APK_SCOPE
        version_key = cls.apk_key(channel, version)
        current_key = cls.apk_key(channel, settings.APK_RELEASE_DIR)
        ret, info = QiniuTool.bucket.stat(apk_scope, current_key)
        info_logger.debug(
            {
                'channel': channel,
                'version': version,
                'version_key': version_key,
                'current_key': current_key,
                'ret': ret
            }
        )
        if ret:
            QiniuTool.delete(current_key, apk_scope)
        QiniuTool.copy(version_key, current_key, apk_scope, apk_scope)
        if need_refresh:
            QiniuTool.refresh(['http://alpha-s.iyanzhi.com/' + current_key])
        return True
