## @file
# This file is used to parse a Package file of .PKG file
#
# Copyright (c) 2011 - 2018, Intel Corporation. All rights reserved.<BR>
#
# SPDX-License-Identifier: BSD-2-Clause-Patent
#

'''
PackageSurfaceAreaXml
'''
from xml.dom import minidom

from edk2basetools.UPT.Library.StringUtils import GetStringOfList
from edk2basetools.UPT.Library.Xml.XmlRoutines import XmlElement
from edk2basetools.UPT.Library.Xml.XmlRoutines import XmlNode
from edk2basetools.UPT.Library.Xml.XmlRoutines import XmlList
from edk2basetools.UPT.Library.Xml.XmlRoutines import CreateXmlElement
from edk2basetools.UPT.Object.POM.CommonObject import IncludeObject
from edk2basetools.UPT.Object.POM.CommonObject import TextObject
from edk2basetools.UPT.Object.POM.PackageObject import PackageObject
from edk2basetools.UPT.Xml.CommonXml import ClonedFromXml
from edk2basetools.UPT.Xml.CommonXml import PackageHeaderXml
from edk2basetools.UPT.Xml.CommonXml import HelpTextXml
from edk2basetools.UPT.Xml.CommonXml import CommonDefinesXml
from edk2basetools.UPT.Xml.CommonXml import LibraryClassXml
from edk2basetools.UPT.Xml.CommonXml import UserExtensionsXml
from edk2basetools.UPT.Xml.CommonXml import MiscellaneousFileXml
from edk2basetools.UPT.Xml.GuidProtocolPpiXml import GuidXml
from edk2basetools.UPT.Xml.GuidProtocolPpiXml import ProtocolXml
from edk2basetools.UPT.Xml.GuidProtocolPpiXml import PpiXml
from edk2basetools.UPT.Xml.ModuleSurfaceAreaXml import ModuleSurfaceAreaXml
from edk2basetools.UPT.Xml.PcdXml import PcdEntryXml

##
# IndustryStandardHeaderXml
#
class IndustryStandardHeaderXml(object):
    def __init__(self):
        self.HeaderFile = ''
        self.HelpText = []

    def FromXml(self, Item, Key):
        self.HeaderFile = XmlElement(Item, '%s/HeaderFile' % Key)
        for HelpTextItem in XmlList(Item, '%s/HelpText' % Key):
            HelpTextObj = HelpTextXml()
            HelpTextObj.FromXml(HelpTextItem, '%s/HelpText' % Key)
            self.HelpText.append(HelpTextObj)

        Include = IncludeObject()
        Include.SetFilePath(self.HeaderFile)
        HelpTxt = TextObject()
        HelpTxt.SetString(self.HelpText)
        Include.SetHelpText(HelpTxt)

        return Include

    def ToXml(self, IndustryStandardHeader, Key):
        if self.HeaderFile:
            pass
        AttributeList = []
        NodeList = [['HeaderFile', IndustryStandardHeader.GetFilePath()]]
        Root = CreateXmlElement('%s' % Key, '', NodeList, AttributeList)

        return Root

    def __str__(self):
        Str = "HeaderFile = %s" % (self.HeaderFile)
        for Item in self.HelpText:
            Str = Str + "\n\t" + str(Item)
        return Str
##
# PackageIncludeHeaderXml
#
class PackageIncludeHeaderXml(object):
    def __init__(self):
        self.HeaderFile = ''
        self.CommonDefines = CommonDefinesXml()
        self.HelpText = []

    def FromXml(self, Item, Key):
        self.HeaderFile = XmlElement(Item, '%s/HeaderFile' % Key)
        self.CommonDefines.FromXml(XmlNode(Item, '%s/HeaderFile' % Key), 'HeaderFile')
        for HelpTextItem in XmlList(Item, '%s/HelpText' % Key):
            HelpTextObj = HelpTextXml()
            HelpTextObj.FromXml(HelpTextItem, '%s/HelpText' % Key)
            self.HelpText.append(HelpTextObj)

        Include = IncludeObject()
        Include.SetFilePath(self.HeaderFile)
        Include.SetSupArchList(self.CommonDefines.SupArchList)
        HelpTxt = TextObject()
        HelpTxt.SetString(self.HelpText)
        Include.SetHelpText(HelpTxt)

        return Include

    def ToXml(self, PackageIncludeHeader, Key):
        if self.HeaderFile:
            pass
        AttributeList = [['SupArchList', GetStringOfList(PackageIncludeHeader.GetSupArchList())], \
                         ['SupModList', GetStringOfList(PackageIncludeHeader.GetSupModuleList())], ]

        HeaderFileNode = CreateXmlElement('HeaderFile', PackageIncludeHeader.FilePath, [], AttributeList)

        NodeList = [HeaderFileNode]
        for Item in PackageIncludeHeader.GetHelpTextList():
            Tmp = HelpTextXml()
            NodeList.append(Tmp.ToXml(Item))

        Root = CreateXmlElement('%s' % Key, '', NodeList, [])

        return Root

    def __str__(self):
        Str = "HeaderFile = %s\n\t%s" % (self.HeaderFile, self.CommonDefines)
        for Item in self.HelpText:
            Str = Str + "\n\t" + str(Item)
        return Str

##
# PcdCheckXml
#
class PcdCheckXml(object):
    def __init__(self):
        self.PcdCheck = ''

    def FromXml(self, Item, Key):
        if Key:
            pass
        self.PcdCheck = XmlElement(Item, 'PcdCheck')

        return self.PcdCheck

    def ToXml(self, PcdCheck, Key):
        if self.PcdCheck:
            pass
        Root = CreateXmlElement('%s' % Key, PcdCheck, [], [])
        return Root

    def __str__(self):
        return "PcdCheck = %s" % (self.PcdCheck)

##
# PackageSurfaceAreaXml
#
class PackageSurfaceAreaXml(object):
    def __init__(self):
        self.Package = None

    def FromXml(self, Item, Key):
        if Key:
            pass
        #
        # Create a package object
        #
        Package = PackageObject()
        #
        # Header
        #
        Tmp = PackageHeaderXml()
        Tmp.FromXml(XmlNode(Item, '/PackageSurfaceArea/Header'), 'Header', Package)
        #
        # ClonedFrom
        #
        Tmp = ClonedFromXml()
        if XmlNode(Item, '/PackageSurfaceArea/ClonedFrom'):
            ClonedFrom = Tmp.FromXml(XmlNode(Item, '/PackageSurfaceArea/ClonedFrom'), 'ClonedFrom')
            Package.SetClonedFromList([ClonedFrom])
        #
        # LibraryClass
        #

        for SubItem in XmlList(Item, '/PackageSurfaceArea/LibraryClassDeclarations/LibraryClass'):
            Tmp = LibraryClassXml()
            LibraryClass = Tmp.FromXml(SubItem, 'LibraryClass')
            Package.SetLibraryClassList(Package.GetLibraryClassList() + [LibraryClass])

        if XmlList(Item, '/PackageSurfaceArea/LibraryClassDeclarations') and \
           not XmlList(Item, '/PackageSurfaceArea/LibraryClassDeclarations/LibraryClass'):
            Package.SetLibraryClassList([None])

        #
        # IndustryStandardHeader
        #
        for SubItem in XmlList(Item, '/PackageSurfaceArea/IndustryStandardIncludes/IndustryStandardHeader'):
            Tmp = IndustryStandardHeaderXml()
            Include = Tmp.FromXml(SubItem, 'IndustryStandardHeader')
            Package.SetStandardIncludeFileList(Package.GetStandardIncludeFileList() + [Include])

        if XmlList(Item, '/PackageSurfaceArea/IndustryStandardIncludes') and \
        not XmlList(Item, '/PackageSurfaceArea/IndustryStandardIncludes/IndustryStandardHeader'):
            Package.SetStandardIncludeFileList([None])


        #
        # PackageHeader
        #
        for SubItem in XmlList(Item, '/PackageSurfaceArea/PackageIncludes/PackageHeader'):
            Tmp = PackageIncludeHeaderXml()
            Include = Tmp.FromXml(SubItem, 'PackageHeader')
            Package.SetPackageIncludeFileList(Package.GetPackageIncludeFileList() + [Include])

        if XmlList(Item, '/PackageSurfaceArea/PackageIncludes') and not \
           XmlList(Item, '/PackageSurfaceArea/PackageIncludes/PackageHeader'):
            Package.SetPackageIncludeFileList([None])

        #
        # Guid
        #
        for SubItem in XmlList(Item, '/PackageSurfaceArea/GuidDeclarations/Entry'):
            Tmp = GuidXml('Package')
            GuidProtocolPpi = Tmp.FromXml(SubItem, 'Entry')
            Package.SetGuidList(Package.GetGuidList() + [GuidProtocolPpi])

        if XmlList(Item, '/PackageSurfaceArea/GuidDeclarations') and not \
           XmlList(Item, '/PackageSurfaceArea/GuidDeclarations/Entry'):
            Package.SetGuidList([None])

        #
        # Protocol
        #
        for SubItem in XmlList(Item, '/PackageSurfaceArea/ProtocolDeclarations/Entry'):
            Tmp = ProtocolXml('Package')
            GuidProtocolPpi = Tmp.FromXml(SubItem, 'Entry')
            Package.SetProtocolList(Package.GetProtocolList() + [GuidProtocolPpi])

        if XmlList(Item, '/PackageSurfaceArea/ProtocolDeclarations') and not \
           XmlList(Item, '/PackageSurfaceArea/ProtocolDeclarations/Entry'):
            Package.SetProtocolList([None])

        #
        # Ppi
        #
        for SubItem in XmlList(Item, '/PackageSurfaceArea/PpiDeclarations/Entry'):
            Tmp = PpiXml('Package')
            GuidProtocolPpi = Tmp.FromXml(SubItem, 'Entry')
            Package.SetPpiList(Package.GetPpiList() + [GuidProtocolPpi])

        if XmlList(Item, '/PackageSurfaceArea/PpiDeclarations') and not \
           XmlList(Item, '/PackageSurfaceArea/PpiDeclarations/Entry'):
            Package.SetPpiList([None])

        #
        # PcdEntry
        #
        for SubItem in XmlList(Item, '/PackageSurfaceArea/PcdDeclarations/PcdEntry'):
            Tmp = PcdEntryXml()
            PcdEntry = Tmp.FromXml2(SubItem, 'PcdEntry')
            Package.SetPcdList(Package.GetPcdList() + [PcdEntry])

            #
            # Get PcdErrorCommentDict from PcdError in PcdEntry Node
            #
            for PcdErrorObj in PcdEntry.GetPcdErrorsList():
                PcdErrorMessageList = PcdErrorObj.GetErrorMessageList()
                if PcdErrorMessageList:
                    Package.PcdErrorCommentDict[(PcdEntry.GetTokenSpaceGuidCName(), PcdErrorObj.GetErrorNumber())] = \
                    PcdErrorMessageList


        if XmlList(Item, '/PackageSurfaceArea/PcdDeclarations') and not \
           XmlList(Item, '/PackageSurfaceArea/PcdDeclarations/PcdEntry'):
            Package.SetPcdList([None])

        #
        # PcdCheck
        #
        for SubItem in XmlList(Item, '/PackageSurfaceArea/PcdRelationshipChecks/PcdCheck'):
            Tmp = PcdCheckXml()
            PcdCheck = Tmp.FromXml(SubItem, 'PcdCheck')
            Package.PcdChecks.append(PcdCheck)

        #
        # Modules
        #
        for SubItem in XmlList(Item, '/PackageSurfaceArea/Modules/ModuleSurfaceArea'):
            Tmp = ModuleSurfaceAreaXml()
            Module = Tmp.FromXml(SubItem, 'ModuleSurfaceArea')
            ModuleDictKey = (Module.GetGuid(), Module.GetVersion(), Module.GetName(), Module.GetModulePath())
            Package.ModuleDict[ModuleDictKey] = Module
        #
        # MiscellaneousFile
        #
        Tmp = MiscellaneousFileXml()
        MiscFileList = Tmp.FromXml(XmlNode(Item, '/PackageSurfaceArea/MiscellaneousFiles'), 'MiscellaneousFiles')
        if MiscFileList:
            Package.SetMiscFileList([MiscFileList])
        else:
            Package.SetMiscFileList([])

        #
        # UserExtensions
        #
        for Item in XmlList(Item, '/PackageSurfaceArea/UserExtensions'):
            Tmp = UserExtensionsXml()
            UserExtension = Tmp.FromXml(Item, 'UserExtensions')
            Package.UserExtensionList.append(UserExtension)

        self.Package = Package
        return self.Package

    def ToXml(self, Package):
        if self.Package:
            pass
        #
        # Create PackageSurfaceArea node
        #
        DomPackage = minidom.Document().createElement('PackageSurfaceArea')
        #
        # Header
        #
        Tmp = PackageHeaderXml()
        DomPackage.appendChild(Tmp.ToXml(Package, 'Header'))
        #
        # ClonedFrom
        #
        Tmp = ClonedFromXml()
        if Package.GetClonedFromList() != []:
            DomPackage.appendChild(Tmp.ToXml(Package.GetClonedFromList[0], 'ClonedFrom'))
        #
        # LibraryClass
        #
        LibraryClassNode = CreateXmlElement('LibraryClassDeclarations', '', [], [])
        for LibraryClass in Package.GetLibraryClassList():
            Tmp = LibraryClassXml()
            LibraryClassNode.appendChild(Tmp.ToXml(LibraryClass, 'LibraryClass'))
        DomPackage.appendChild(LibraryClassNode)
        #
        # IndustryStandardHeader
        #
        IndustryStandardHeaderNode = CreateXmlElement('IndustryStandardIncludes', '', [], [])
        for Include in Package.GetStandardIncludeFileList():
            Tmp = IndustryStandardHeaderXml()
            IndustryStandardHeaderNode.appendChild(Tmp.ToXml(Include, 'IndustryStandardHeader'))
        DomPackage.appendChild(IndustryStandardHeaderNode)
        #
        # PackageHeader
        #
        PackageIncludeHeaderNode = CreateXmlElement('PackageIncludes', '', [], [])
        for Include in Package.GetPackageIncludeFileList():
            Tmp = PackageIncludeHeaderXml()
            PackageIncludeHeaderNode.appendChild(Tmp.ToXml(Include, 'PackageHeader'))
        DomPackage.appendChild(PackageIncludeHeaderNode)
        ModuleNode = CreateXmlElement('Modules', '', [], [])
        for Module in Package.GetModuleDict().values():
            Tmp = ModuleSurfaceAreaXml()
            ModuleNode.appendChild(Tmp.ToXml(Module))
        DomPackage.appendChild(ModuleNode)
        #
        # Guid
        #
        GuidProtocolPpiNode = CreateXmlElement('GuidDeclarations', '', [], [])
        for GuidProtocolPpi in Package.GetGuidList():
            Tmp = GuidXml('Package')
            GuidProtocolPpiNode.appendChild(Tmp.ToXml\
                                            (GuidProtocolPpi, 'Entry'))
        DomPackage.appendChild(GuidProtocolPpiNode)
        #
        # Protocol
        #
        GuidProtocolPpiNode = \
        CreateXmlElement('ProtocolDeclarations', '', [], [])
        for GuidProtocolPpi in Package.GetProtocolList():
            Tmp = ProtocolXml('Package')
            GuidProtocolPpiNode.appendChild\
            (Tmp.ToXml(GuidProtocolPpi, 'Entry'))
        DomPackage.appendChild(GuidProtocolPpiNode)
        #
        # Ppi
        #
        GuidProtocolPpiNode = CreateXmlElement('PpiDeclarations', '', [], [])
        for GuidProtocolPpi in Package.GetPpiList():
            Tmp = PpiXml('Package')
            GuidProtocolPpiNode.appendChild\
            (Tmp.ToXml(GuidProtocolPpi, 'Entry'))
        DomPackage.appendChild(GuidProtocolPpiNode)
        #
        # PcdEntry
        #
        PcdEntryNode = CreateXmlElement('PcdDeclarations', '', [], [])
        for PcdEntry in Package.GetPcdList():
            Tmp = PcdEntryXml()
            PcdEntryNode.appendChild(Tmp.ToXml2(PcdEntry, 'PcdEntry'))
        DomPackage.appendChild(PcdEntryNode)

        #
        # MiscellaneousFile
        #
        Tmp = MiscellaneousFileXml()
        if Package.GetMiscFileList():
            DomPackage.appendChild(Tmp.ToXml(Package.GetMiscFileList()[0], 'MiscellaneousFiles'))

        #
        # UserExtensions
        #
        if Package.GetUserExtensionList():
            for UserExtension in Package.GetUserExtensionList():
                Tmp = UserExtensionsXml()
                DomPackage.appendChild(Tmp.ToXml(UserExtension, 'UserExtensions'))

        return DomPackage
