#!/usr/bin/env python3
# -*- coding:utf-8 -*-
#############################################################################
# Copyright (c): 2012-2017, Huawei Tech. Co., Ltd.
# Description  : ParseXml.py is a utility to parse xml file
#############################################################################
try:
    import os
    import sys
    import re
    import xml.etree.cElementTree as ETree

    sys.path.append(os.path.split(os.path.realpath(__file__))[0] + "/../../../")
    from gspylib.common.ErrorCode import ErrorCode
    from gspylib.common.cluster_topology import const
except ImportError as ie:
    sys.exit("[GAUSS-52200] : Unable to import module: %s." % str(ie))


class ParseXml():
    def __init__(self):
        pass

    def findParamByName(self, nodeName, paraName, DeviceNode):
        """
        function : Find parameter by name
        input : String,String,Object
        output : String,String
        """
        returnValue = ""
        returnStatus = 2
        for dev in DeviceNode:
            paramList = dev.findall('PARAM')
            for param in paramList:
                thisname = param.attrib['name']
                if thisname == 'name':
                    value = param.attrib['value']
                    if nodeName == value:
                        for tmp in paramList:
                            name = tmp.attrib['name']
                            if name == paraName:
                                returnStatus = 0
                                returnValue = str(tmp.attrib['value']).strip()
                                if (name.find("Dir") > 0 or name.find("dataNode") == 0) and returnValue != "":
                                    returnValue = os.path.normpath(returnValue)
        return returnStatus, returnValue

    def findParamInCluster(self, paraName, nodeArray):
        """
        function : Find parameter in cluster
        input : String,[]
        output : String,String
        """
        returnValue = ""
        returnStatus = 2
        for node in nodeArray:
            name = node.attrib['name']
            if name == paraName:
                returnStatus = 0
                returnValue = str(node.attrib['value'])
        return returnStatus, returnValue

    def readOneClusterConfigItem(self, rootNode, paraName, inputElementName, nodeName=""):
        """
        function : Read one cluster configuration item
        input : Object,String,String
        output : String,String
        """
        # if read node level config item, should input node name
        if inputElementName.upper() == 'node'.upper() and nodeName == "":
            raise Exception(ErrorCode.GAUSS_512["GAUSS_51201"] +
                            " Need node name for node configuration level.")

        ElementName = inputElementName.upper()
        # get config path

        if ElementName == 'cluster'.upper():
            element = rootNode.findall('CLUSTER')[0]
            nodeArray = element.findall('PARAM')
            (returnStatus, returnValue) = self.findParamInCluster(paraName, nodeArray)
        elif ElementName == 'node'.upper():
            ElementName = 'DEVICELIST'
            DeviceArray = rootNode.findall('DEVICELIST')[0]
            DeviceNode = DeviceArray.findall('DEVICE')
            (returnStatus, returnValue) = self.findParamByName(nodeName, paraName, DeviceNode)
        else:
            raise Exception(ErrorCode.GAUSS_512["GAUSS_51200"] % ElementName)

        return returnStatus, returnValue

    def checkXMLFile(self, xmlFile):
        """
        function : check XML contain DTDs
        input : String
        output : NA
        """
        # Check xml for security requirements
        # if it have "<!DOCTYPE\s+note\s+SYSTEM",
        # exit and print "File have security risks."
        try:
            with open(xmlFile, "r") as fp:
                lines = fp.readlines()
            for line in lines:
                if re.findall("<!DOCTYPE\s+note\s+SYSTEM", line):
                    raise Exception("File have security risks.")
        except Exception as e:
            raise Exception(str(e))

    def initParserXMLFile(self, xmlFilePath):
        """
        function : Init parser xml file
        input : String
        output : Object
        """
        try:
            # check xml for security requirements
            self.checkXMLFile(xmlFilePath)
            # parse the xml by xml.etree.cElementTree
            domTree = ETree.parse(xmlFilePath)
            rootNode = domTree.getroot()
        except Exception as e:
            raise Exception(ErrorCode.GAUSS_512["GAUSS_51236"] + " Error: \n%s." % str(e))
        return rootNode

    def setDefaultXmlFile(self, xmlFile):
        """
        function : Set the default xml file
        input : String
        output : NA
        """
        if not os.path.exists(xmlFile):
            raise Exception(ErrorCode.GAUSS_502["GAUSS_50201"] % "XML configuration")

        os.putenv(const.ENV_CLUSTERCONFIG, xmlFile)

    def checkPathVaild(self, envValue):
        """
        function: check path vaild
        input : envValue
        output: NA
        """
        PATH_CHECK_LIST = ["|", ";", "&", "$", "<", ">", "`", "\\", "'", "\"", "{", "}", "(", ")", "[", "]", "~", "*",
                           "?", " ", "!", "\n"]
        if envValue.strip() == "":
            return
        for rac in PATH_CHECK_LIST:
            flag = envValue.find(rac)
            if flag >= 0:
                raise Exception(ErrorCode.GAUSS_502["GAUSS_50219"] % envValue +
                                " There are illegal characters in the path.")
