# -*- coding: UTF-8 -*-
from com.huawei.ism.tlv.lang import UnsignedInt32
from com.huawei.ism.tlv.bean import Param
from com.huawei.ism.tlv.docoder import ParamType
from com.huawei.ism.tlv import TLVUtils
import os
import re
import shutil
from common import resourceParse
from common.constant import *
from common.baseFactory import log
from cbb.business.checkitems import patch_ver_match_check
from service.patch_multi_service import PatchMultiPackagesManager
from cbb.frame.util.tar_util import decompress_tar_special_file


# *************************************************************#
# 函数名称: getHotPatchPKGVersion
# 功能说明: 解压热补丁包的配置文件，获取热补丁包版本号配套关系
# 其 他   :  无
# *************************************************************#  
def getPatchPKGVersion(data_dict, filePath):
    """
    功能说明：解析补丁包，获取补丁包类型、热补丁版本、热补丁B版本、异构补丁名称和异构补丁版本
   输入：补丁包路径。
  输出：bool解析成功结果False/True，dict获取的补丁包信息(patchType、hotPatchPkgVersion、SysVersionBSupported、AslName、AslVersion)
    """
    packageVersion = {}
    packageValid = False
    
    extractPath = filePath[0: filePath.index('.tgz')]
    
    try:
        # 查看热补丁包是否有效
        # 普通热补丁包：patch.conf文件在第一层压缩目录下
        # 补丁包无效，直接返回为空
        packageValid, _ = decompress_tar_special_file(filePath, extractPath, 'patch.conf')
        if not packageValid:
            log.warn(data_dict, 'not find patch.conf, its not a mult hotpatch')
            return packageValid, "", "", ""
    
        #解析补丁配置文件
        confFile = extractPath + os.sep + 'patch.conf'
        conFileFd = open(confFile, "r")
        confInfo = conFileFd.read()
        #关闭文件句柄
        conFileFd.close()
        lineList = confInfo.splitlines()
        
        #获取配置文件中的热补丁版本号
        for line in lineList:
    
            field = line.split()
            if len(field) < 2:
                continue
            #获取版本配置信息
            if field[0] == "Version":
                packageVersion['hotPatchPkgVersion'] = field[1]
            elif field[0] == "PATCHTYPE":
                packageVersion['patchType'] = field[1]
            elif field[0] == "SysVersionBSupported":
                packageVersion['SysVersionBSupported'] = field[1]
            elif field[0] == 'Asl_Version':
                packageVersion['AslVersion'] = field[1]
            elif field[0] == 'Asl_Name':
                packageVersion['AslName'] = field[1]
            elif field[0] == 'SysVersionSupported':
                packageVersion['SysVersionSupported'] = field[1]
            else:
                continue
    except Exception as e:
        log.error(data_dict, 'parse patch.conf config happened exception, failed={}'.format(str(e)))
        packageValid = False
    finally:
        shutil.rmtree(filePath[0:-4], ignore_errors=True)
    
    return (packageValid,packageVersion)

def getHotPatchCurVersion(dataDict):
    """
    功能说明：查询当前阵列已安装的热补丁版本号
    输入：工具框架上下文
    返回：bool查询成功结果False/True，str热补丁版本号
    """
    tlvCon = dataDict["tlv"]
    msgParam0 = Param(0, ParamType.UNSIGN_INT, UnsignedInt32(TLV_PACKAGE_TYPE.HOT_PATCH_PKG))
    params = TLVUtils.paramList(msgParam0)
    retRec = tlvCon.invoke(TLV_CMD.OM_MSG_OP_LST_VER, params, CMD_DEFAULT_TIMEOUT)
    log.info(dataDict,'TLV cmd [%d] send[%s] receive[%s]'%(TLV_CMD.OM_MSG_OP_LST_VER,str(params),str(retRec)))
    curHotPatchVersion = retRec.getParamStrValue(4)
    if not curHotPatchVersion:
        log.error(dataDict,'Get curHotPatchVersion failed')
        return (True,'--')
    return (True,curHotPatchVersion)
    
def getAslPatchCurVersion(dataDict):
    """
    功能说明：查询当前阵列已安装的异构补丁版本号
    输入：工具框架上下文
    返回：bool查询成功结果False/True，str异构补丁版本号
    """
    curAslPatchVersions = ''
    tlvCon = dataDict["tlv"]
    msgParam0 = Param(0, ParamType.UNSIGN_INT, UnsignedInt32(TLV_PACKAGE_TYPE.ASL_PATCH_PKG))
    params = TLVUtils.paramList(msgParam0)
    recs = tlvCon.getBatch(TLV_CMD.OM_MSG_OP_LST_VER, params, CMD_DEFAULT_TIMEOUT)
    log.info(dataDict,'TLV cmd [%d] send[%s] receive[%s]'%(TLV_CMD.OM_MSG_OP_LST_VER,str(params),str(recs)))
    itemNum = recs.size()
    for index in range(0,itemNum):
        curAslPatchVersioninfo = recs.get(index)
        if index == 0:
            result = curAslPatchVersioninfo.getParamIntValue(0).intValue()
            log.info(dataDict,'getAslPatchCurVersion result:'+str(result))
            if result != 0:
                log.error(dataDict,'Get AslPatchCurVersion failed   result:'+ str(result))
                return (True,curAslPatchVersions)
        else:
            AslPatchName = curAslPatchVersioninfo.getParamStrValue(4)
            log.info(dataDict,'AslPatchName:'+AslPatchName)
            AslPatchVersion = curAslPatchVersioninfo.getParamStrValue(5)
            log.info(dataDict,'AslPatchVersion:'+AslPatchVersion)
            curAslPatchVersions += AslPatchName + ' ' + AslPatchVersion + '; '
    return (True,curAslPatchVersions)

# *************************************************************#
# 函数名称: execute
# 功能说明: 解析热补丁包所在路径，返回字典：热补丁版本号+对应的文件名(入口函数)
# 其 他   :  无
# *************************************************************#
def execute(dataDict):
    """
          函数名称: execute
         功能说明: 解析热补丁包所在路径，返回字典：补丁包版本号+当前阵列补丁版本号(入口函数)
        其 他   :  无
    """
    context = dataDict.get("context")
    lang = dataDict.get("lang")
    curPatchVersion = ''
    hotPatchPKGVersion = ''
    hotPatchTgzPkgName = dataDict['packagePath']
    deviceSN = str(dataDict.get('dev').getDeviceSerialNumber())
    checkDict = {}
    # 解析resource文件并保存
    resource = resourceParse.execute(lang)
    dataDict["resource"] = resource
    errMsg = ''
    if False == os.path.isfile(hotPatchTgzPkgName):
        log.error(dataDict,'patchPath is follow')
        log.error(dataDict, hotPatchTgzPkgName)
        errMsg = resource.get('upload.pkgPathAbnormality')
        return False, errMsg, checkDict

    manager = PatchMultiPackagesManager(dataDict, hotPatchTgzPkgName)
    if manager.is_multi_patch_package():
        if not manager.is_valid_multi_package():
            log.error(dataDict, 'Patch multi package invalid')
            return False, resource.get('upload.pkgInvalid'), checkDict
        hotPatchTgzPkgName = manager.get_last_patch_package()
        log.info(dataDict, "multi patch packages")

    # 获取补丁包信息
    iRet = getPatchPKGVersion(dataDict, hotPatchTgzPkgName)
    manager.del_child_directory()
    packageValid = iRet[0]
    if not packageValid:
        log.error(dataDict, 'Patch package invalid')
        errMsg = resource.get('upload.pkgInvalid')
        return False, errMsg, checkDict
    
    packageVersion = iRet[1]
    pkgVersion = packageVersion.get('hotPatchPkgVersion')
    patchType = packageVersion.get('patchType')
    pkgSystemSpcVerComp = packageVersion.get('SysVersionBSupported')
    AslVersion = packageVersion.get('AslVersion')
    AslName = packageVersion.get('AslName')
    
        
    #判断补丁类型（热补丁、异构补丁）如果为空则为热补丁
    if not patchType:
        patchType = PATCH_TYPE.HOT_PATCH
        #we just need the version like this: VxxxRxxxCxx
        sysVersion = re.compile(r'^V\d{0,3}R\d{0,3}C\d{0,2}')
        if not pkgSystemSpcVerComp or not pkgVersion:
            errMsg = resource.get('upload.pkgAbnormality')
            return (False,errMsg,checkDict)
        tempResult = sysVersion.search(pkgSystemSpcVerComp)
        if tempResult is None:
            pkgSystemSpcVerComp = ""
        else:
            pkgSystemSpcVerComp = tempResult.group()
    elif patchType != PATCH_TYPE.ASL_PATCH:
        log.error(dataDict,u'获取补丁包类型异常   PATCH_TYPE:' +patchType)
        errMsg = resource.get('upload.pkgTypeAbnormality')
        return (False, errMsg,checkDict)

    # 检查-1补丁的VRC版本是否和阵列的VRC版本匹配
    flag, err_msg = patch_ver_match_check.execute(dataDict, packageVersion)
    if not flag:
        return False, err_msg, checkDict

    #查询当前阵列安装的补丁版本号
    if patchType == PATCH_TYPE.HOT_PATCH:
        ret = getHotPatchCurVersion(dataDict)
        if not ret[0]:
            log.error(dataDict,'gethotpatchversion failed')
        else:
            curPatchVersion = ret[1]
        hotPatchPKGVersion = pkgSystemSpcVerComp + pkgVersion
    else:
        if not AslName or not AslVersion:
           errMsg = resource.get('upload.pkgAbnormality')
           return (False,errMsg,checkDict)
        ret = getAslPatchCurVersion(dataDict)
        if not ret[0]:
            log.error(dataDict,'getaslpatchversion failed')
        else:
            curPatchVersion = ret[1]
        hotPatchPKGVersion = AslName + ' ' + AslVersion
    #将补丁类型放入框架公共字典
    context["patchType_%s"%deviceSN] = patchType
    #填充返回字典      
    checkDict = {"hotPatchVersion": hotPatchPKGVersion,'curPatchVersion':curPatchVersion}
    context["hotPatchPKGVersion_%s"%deviceSN] = hotPatchPKGVersion
    #检查结果返回
    return (True, errMsg, checkDict)
