# -*- coding: UTF-8 -*-
import ConfigParser
import json
import os
import re
import sys
import time

# from compare_dependency import CompareDependency
from encrypt_tool.encrypt_app import CryptApp

DIR_PATH = os.path.split(os.path.realpath(__file__))[0]
BASE_PATH = os.path.split(DIR_PATH)[0]


class Package(object):
    def __init__(self):
        # 第一步：初始化一些变量，获取app fold name 版本等等
        self.__svn_up()
        self.app_name = self.__get_app_name()
        self.version = self.__get_app_version()
        self.work_path_base = '/tmp'
        # 输出的dat包放置的位置，默认与package.py 放在同级目录
        self.package_out_path = DIR_PATH
        # 打包的临时目录
        self.app_work_path = os.path.normpath(os.path.join(self.work_path_base, self.app_name))
        print self.app_work_path
        # 清理tmp目录下面的已有的
        os.system("rm -rf " + self.app_work_path)
        # 不加密的py目录
        self.py_not_encnrypt_list = self.__get_py_not_encrypt()
        # 第二步：选择编译前端代码,npm run build
        self.packageFrontEnd()
        # 第三步：获取svn版本号
        # self.build_version = self.__get_svn()
        self.build_version = "cf71606"
        self.package_name = "%s.%s.%s.tar.gz" % (self.app_name, self.version, self.build_version)
        # 第五步：拷贝需要打包进组件的目录和文件到临时目录
        self.do_copy_work_dir()
        # 第六步：检查加密的包配置
        self.__get_encrypt_conf()
        # 第七步：把build_version 写到文件里面
        self.__set_build_version()
        # 第八步：检查加密py的配置
        self.__do_encrypt_file()
        # 第九步：加密py
        self.run_encrypt()

    def __get_app_name(self):
        with open(os.path.join(BASE_PATH, "package.json"), "r+") as f:
            pkgConfig = json.load(f)
        return pkgConfig["name"]
    def __get_app_version(self):
        with open(os.path.join(BASE_PATH, "package.json"), "r+") as f:
            pkgConfig = json.load(f)
        return pkgConfig["version"]
    def __get_py_not_encrypt(self):
        return {
            'files': [
                # os.path.normpath(APP_WORK_PATH + os.sep + 'install.py'),
                # os.path.normpath(APP_WORK_PATH + os.sep + "bin" + os.sep + "start.py"),
                # os.path.normpath(APP_WORK_PATH + os.sep + "bin" + os.sep + "check.py"),
            ],
            'paths': [
                os.path.normpath(self.app_work_path + os.sep + 'target'),
                os.path.normpath(self.app_work_path + os.sep + 'static'),
            ],
        }

    def __svn_up(self):
        # 更新svn到最新
        # cmd = "cd %s && git pull " % BASE_PATH
        # os.system(cmd)
        pass

    def __get_svn(self):
        return 10000
        # svnPath = BASE_PATH
        # try:
        #     cmd = 'cd %s && svn info' % svnPath
        #     svnContent = os.popen(cmd).read()
        #     lang = os.popen('echo $LANG').read()
        #     if 'en_US' in lang:
        #         revision = 'Rev'
        #     elif 'zh_CN' in lang:
        #         revision = '最后修改的版本'
        #     else:
        #         print 'system language is not found'
        #         sys.exit(1)
        #     svnRe = re.compile('%s: (\d*?)\n' % revision)
        #     svn_revision = svnRe.findall(svnContent)[0]
        #     print 'svn_revision : %s cmd : %s' % (svn_revision, cmd)
        # except Exception, e:
        #     print 'get SVN revision Failed. %s' % (str(e))
        #     sys.exit(1)
        # return svn_revision

    def do_copy_work_dir(self):
        print '拷贝数据到临时目录'
        os.chdir(BASE_PATH)
        cmd = 'rsync -az * --include="static/dist" --include="static/icon" --exclude="static/*" %s' % (
            self.app_work_path)
        print cmd
        os.system(cmd)
        print '拷贝完成'

    def __get_encrypt_conf(self):
        sections_dict = dict()
        conf_path = os.path.normpath(os.path.join(self.app_work_path, 'target', 'encrypt_conf'))
        if not os.path.exists(conf_path):
            print 'conf file is not exists...'
            return
        try:
            cf = ConfigParser.ConfigParser()
            cf.read(conf_path)
            sections = cf.sections()
            for section in sections:
                options = cf.options(section)
                options_dic = dict()
                for option in options:
                    try:
                        value = cf.get(section, option).decode('utf-8', 'ignore')
                    except Exception, e:
                        value = cf.get(section, option)
                    options_dic[option] = value
                sections_dict[section] = options_dic
        except Exception, e:
            print 'error', str(e)
        try:
            self.is_dat = int(sections_dict['encrypt'].get('is_dat', 0))
        except:
            pass
        try:
            self.is_pyc = int(sections_dict['encrypt'].get('is_pyc', 0))
        except:
            pass
        try:
            self.is_front_pac = int(sections_dict['encrypt'].get('is_front_pac', 0))
        except:
            pass
        try:
            self.is_front_enc = int(sections_dict['encrypt'].get('is_front_enc', 0))
        except:
            pass

    def __set_build_version(self):
        print "set package name ..."
        try:
            app_version_file = os.path.normpath(os.path.join(self.app_work_path, 'conf', 'buildversion'))
            with open(app_version_file, 'w') as fw:
                fw.write(self.build_version)
        except Exception, e:
            print e
        print "set package name done"

    def __do_encrypt_file(self):
        encrypt_pt_path = os.path.normpath(os.path.join(DIR_PATH, 'encrypt_tool', 'pyprotect.py'))
        print "start encrypt python file ..."
        for root, dirs, files in os.walk(self.app_work_path):
            if root in self.py_not_encnrypt_list['paths']:
                continue
            for fname in files:
                pyPath = os.path.normpath(os.path.join(root, fname))
                if not fname.endswith('.py'):
                    continue
                if pyPath in self.py_not_encnrypt_list['files']:
                    continue
                cmd = "python '%s' '%s'" % (encrypt_pt_path, pyPath)
                os.system(cmd)
                # print cmd
                os.remove(pyPath)
        print "encrypt python file done"

    def packageFrontEnd(self):
        st = time.time()
        print "package static folder start ..."
        os.system('cd %s/static && npm install && npm run build' % BASE_PATH)
        et = time.time()
        print "package static folder done"
        print 'take time for %sS' % (et - st)

    def run_encrypt(self):
        print "package ..."
        install_py = ""
        os.chdir(self.work_path_base)
        # 把install 挪到和app 目录同级
        # 判断install.py 存不存在，如果不存在，不必拷贝
        if os.path.exists(os.path.join(self.app_work_path, "install.py")) or os.path.exists(
                os.path.join(self.app_work_path, "install.pyc")):
            install_py = "install.pyc"
            os.system("mv %s/%s ." % (self.app_name, install_py))
            os.system("tar -zcf %s %s/ %s --exclude=.svn  --exclude=%s/target --exclude=%s/java "
                      "> /dev/null " % (self.package_name, self.app_name, install_py, self.app_name, self.app_name))
        else:
            print "tar -zcf %s %s/ --exclude=.svn  --exclude=%s/target --exclude=%s/java > /dev/null " % (
            self.package_name, self.app_name, self.app_name, self.app_name)
            os.system("tar -zcf %s %s/ --exclude=.svn  --exclude=%s/target --exclude=%s/java > /dev/null " % (
            self.package_name, self.app_name, self.app_name, self.app_name))
            print '执行成功'
        replace_reg = re.compile(r'tar.gz$')
        output_name = replace_reg.sub('dat', self.package_name)
        do_encrypt = CryptApp(self.package_name, output_name)
        do_encrypt.encrypt_app()
        # 删除 tar包  保留加密包
        os.system("rm -rf %s " % self.package_name)
        if install_py:
            os.system("mv %s %s" % (install_py, self.app_name))
        os.system("mv %s %s -f" % (output_name, DIR_PATH))
        self.package_name = output_name
        print "package done"
        self.__info()

    def __info(self):
        print '\033[0;33m'
        print "*********************************"
        print "package ok. "
        print "package name:", self.package_name
        outputfile = os.path.join(self.package_out_path, self.package_name)
        md5 = os.popen("md5sum %s" % outputfile).readlines()[0].strip()
        print "package path:", md5.split(' ')[-1]
        print "package md5:", md5.split(' ')[0]
        print '>>>>>>', 'is_dat:', 'yes' if self.is_dat else 'no'
        print '>>>>>>', 'is_pyc:', 'yes' if self.is_pyc else 'no'
        print '>>>>>>', 'is_front_enc:', 'yes' if self.is_front_enc else 'no'
        print '>>>>>>', 'is_front_pac:', 'yes' if self.is_front_pac else 'no'
        print "*********************************"
        print '\033[0m'

    def do_remove_work_dir(self):
        cmd = 'rm %s -rf' % self.app_work_path
        os.system(cmd)
        # print 'remove %s successfully...' % (APP_WORK_PATH)


def usage():
    print "usage:"
    print "python package.py        ----   run script without a parameter, make a encrypted package"


if __name__ == '__main__':
    '''
        "python package.py        ----   run script without a parameter, make a encrypted package"
    '''
    main_param = sys.argv
    # 清除已经安装的包
    for fileitem in os.listdir(BASE_PATH + "/target"):
        if fileitem.endswith(".dat"):
            os.remove(BASE_PATH + "/target/" + fileitem)
    if len(main_param) == 1:
        Package()
    else:
        usage()
