# -*- coding: UTF-8 -*-

import re
import os
import shutil
import tarfile
import resourceParse
import getPatchInXml
from cbb.frame.util.tar_util import UnZipLimit, get_safe_entry_name

VERSIONS_MAPFILE = r"..{0}conf{0}versionsConf".format(os.sep)

# *************************************************************#
# 函数名称: getVersionsMapAndSave
# 功能说明: 获取xml文件中，热补丁与系统版本配套关系，并写入文件保存
# 其 他   :  无
# *************************************************************#  
def getVersionsMapAndSave(logger):
    
    #热补丁版本号+系统SPC版本号对应关系
    VersionMap = {}
    
    scriptPath = os.path.split(os.path.realpath(__file__))[0]
    verFile = scriptPath + os.sep + VERSIONS_MAPFILE
    
    #调用解析xml文件，获取版本配套关系
    # 补丁工具代码流程优化 modified 20131112 Begin
    iRet = getPatchInXml.getVersionMap()
    # 补丁工具代码流程优化 modified 20131112 End
    VersionMap = iRet

    #获取的映射关系，保存到文件中，供后面脚本使用
    try:
        verMapFileFp = open(verFile, "w")
        verMapFileFp.write("<VersionMap>\n")
        
        for key in VersionMap:
            writeInfo = key + "=" + VersionMap[key] + "\n"
            verMapFileFp.write(writeInfo)
        
        verMapFileFp.write("<\VersionMap>\n")
        verMapFileFp.close()
    except Exception, e:
        return (False, VersionMap)
    
    return (True, VersionMap)

# *************************************************************#
# 函数名称: decompressionUpgradePKG
# 功能说明: 解压热补丁包的配置文件(需要支持普通热补丁包和特殊热补丁包)
# 其 他   :  无
# *************************************************************#  
def decompressionUpgradePKG(filePath):

    extractPath = filePath[0: filePath.index('.tgz')]
    specialPkgFlag = False
    limit = UnZipLimit()
    with tarfile.open(filePath, "r:gz") as tarobj:
        for tarSubFile in tarobj:
            # 通过热补丁包中的tool.conf脚本判断是否为特殊热补丁包
            # 普通热补丁包：patch.conf文件在第一层压缩目录下
            if tarSubFile.name not in ['tool.conf', 'patch.conf']:
                continue
            limit.increase_file_size(tarSubFile.size)
            if limit.is_file_size_over_limit():
                return False, specialPkgFlag
            tarobj.extract(tarSubFile.name, extractPath)
            specialPkgFlag = (tarSubFile.name == "tool.conf")
            return True, specialPkgFlag
    return False, specialPkgFlag

# *************************************************************#
# 函数名称: getCurrentHotPatchInfo
# 功能说明: 获取每一个热补丁包对应关系：热补丁版本号+热补丁包文件名
# 其 他   :  无
# *************************************************************#  
def getCurrentHotPatchInfo(hotPatchName, VersionMap):

    #热补丁字典信息：补丁版本号+热补丁文件名
    hotPatchInfo = {"Version": "", "FilePath": ""}
    hotPatchInfoList = []

    sysVersion = ""
    #P12V-2927 增加热补丁版本号校验 added 20130724 Begin
    confiHotPatchVer = ""
    #P12V-2927 增加热补丁版本号校验 added 20130724 End
    versionValue = ""
    totalHotPatchVersion = ""
    totalHotPatchVersionTmp = ""
    totalHotPatchVersionList = []
    vaildPkgFlag = False
    specialPkgFlag = False
    
    extractPath = hotPatchName[0:-4]

    #由调用者保证.tgz格式的热补丁升级包
    if hotPatchName[-4:] != ".tgz":
        return None
    
    try:
        #解压.tgz升级包文件，提取patch.conf文件
        iRet = decompressionUpgradePKG(hotPatchName)
        specialPkgFlag = iRet[1]
        if True == iRet[0]:
            
            #特殊热补丁包：解析tool.conf文件
            if specialPkgFlag:
                confFile = extractPath + os.sep + 'tool.conf'
            #正常热补丁包：解析patch.conf文件
            else:
                confFile = extractPath + os.sep + 'patch.conf'
            
            conFileFd = open(confFile, "r")
            confInfo = conFileFd.read()
            #关闭文件句柄
            conFileFd.close()
            lineList = confInfo.splitlines()
            
            """普通热补丁包和特殊热补丁包的分支处理"""
            for line in lineList:
                #普通热补丁包
                if not specialPkgFlag:
                    field = line.split()
                    if len(field) < 2:
                        continue
                    #P12V-2927 增加热补丁版本号校验 modified 20130724 Begin
                    #获取配置文件中的热补丁版本号
                    if field[0] == "Version":
                        confiHotPatchVer = field[1]
                    #获取基础版本号
                    if field[0] == "SysVersionSupported":
                        sysVersion = field[1]
                    # 补丁工具代码流程优化 modified 20131112 Begin
                    if confiHotPatchVer != "" and sysVersion != "":
                        #通过系统版本号1180211301来匹配versionMap信息
                        
                        for key in VersionMap:
                            versionValue = VersionMap[key]

                            if re.search(sysVersion, versionValue, re.IGNORECASE):
                                #热补丁完整版本号:S5600T V100R002C00SPHc01
                                totalHotPatchVersion = key
                                #校验热补丁版本号
                                if re.search(confiHotPatchVer, key, re.IGNORECASE):
                                    vaildPkgFlag = True
                                    totalHotPatchVersionList.append(totalHotPatchVersion)
                            else:
                                continue
                        break
                    else:
                        continue
                    # 补丁工具代码流程优化 modified 20131112 End
                    #P12V-2927 增加热补丁版本号校验 modified 20130724 End
                #特殊热补丁包
                else:
                    #特殊热补丁包可能配置多个基础版本
                    field = line.split("=")
                    if len(field) == 2:
                        sysVersion = field[0]
                        #通过系统版本号1180211301来匹配versionMap信息
                        versionValue = VersionMap[sysVersion]
                        if versionValue != None:
                            #热补丁完整版本号:S5600T V100R002C00SPHc01
                            totalHotPatchVersionTmp = versionValue.split("=")[0]
                            totalHotPatchVersionList.append(totalHotPatchVersionTmp)
                            vaildPkgFlag = True
                    else:
                        continue                    
                    
            
    except Exception, e:
        pass
    finally:
        shutil.rmtree(hotPatchName[0:-4], ignore_errors=True)

    #设置热补丁信息
    # 补丁工具代码流程优化 modified 20131112 Begin
    if True == vaildPkgFlag:
        for tempInfo in totalHotPatchVersionList:
            #每次循环均初始化
            hotPatchInfo = {"Version": "", "FilePath": ""}
        
            hotPatchInfo["FilePath"] = hotPatchName
            hotPatchInfo["Version"] = tempInfo
            hotPatchInfoList.append(hotPatchInfo)

        return (hotPatchInfoList, specialPkgFlag)
    else:
        return None
    # 补丁工具代码流程优化 modified 20131112 End

# *************************************************************#
# 函数名称: execute
# 功能说明: 解析热补丁包所在路径，返回字典：热补丁版本号+对应的文件名(入口函数)
# 其 他   :  无
# *************************************************************#
def execute(dataDict):
    #热补丁字典信息：补丁版本号+热补丁文件名
    hotPatchInfo = {"Version": "", "FilePath": ""}
    hotPatchInfoList = []
    
    #解析结果
    parseResults = {}
    #有效的热补丁包列表
    hotPatchFiles = []
    #解析结果
    parseFlag = True
    errMsg = ""

    lang = dataDict.get("lang")
    path = dataDict.get("parsePath")
    logger = dataDict.get("logger")
    fileFlag = os.path.isfile(path)
    
    #解析resource文件并保存
    resource = resourceParse.execute(lang)
    dataDict["resource"] = resource
    specialPkgFlag = False
    
    #从xml文件中获取版本配套关系并保存
    VersionMap = {}
    iRet = getVersionsMapAndSave(logger)
    VersionMap = iRet[1]

    """获取传入Path中的所有热补丁包名List"""
    #如果传入的是文件的绝对路径
    if True == fileFlag:
        fileName = path
        #传入的只能为.tgz的压缩包
        if fileName[-4:] == ".tgz":
            hotPatchFiles.append(fileName)
    #如果传入的是文件夹的绝对路径
    else:
        files = os.listdir(path)
        for file in files:
            #热补丁升级包必须为.tgz格式
            if file[-4:] == ".tgz":
                hotPatchFiles.append(path + os.sep + file)
    
    #解析所有的热补丁升级包，将升级包版本号与文件名对应
    for tgzFileName in hotPatchFiles:
        iRet = getCurrentHotPatchInfo(tgzFileName, VersionMap)
        if iRet != None:
            hotPatchInfoList = iRet[0]
            specialPkgFlag = iRet[1]
            #特殊热补丁包可能配置多个系统版本对应关系
            for hotPatchInfo in hotPatchInfoList:
                parseResults[hotPatchInfo["Version"]] = hotPatchInfo["FilePath"]

    #如果解析结果为空，则返回False
    if parseResults == {}:
        parseFlag = False
        errMsg = resource.get("2006")

    #保存是否为特殊热补丁包Flag(设置为默认值)
    dataDict["SpecialPkg"] = False
    
    #查询当前所有的热补丁包是否名字带有空格
    for key in parseResults:
        filePath = parseResults.get(key)
        fileName = filePath.split(os.sep)[-1]
        if re.search(" ", fileName):
            parseFlag = False
            errMsg = resource.get("2013")
            break

    return (parseFlag, errMsg, parseResults)
