# @file LibraryClassCheck.py
#
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: BSD-2-Clause-Patent
##
import logging
import os
from edk2toolext.environment.plugintypes.ci_build_plugin import ICiBuildPlugin
from edk2toollib.uefi.edk2.parsers.dec_parser import DecParser
from edk2toollib.uefi.edk2.parsers.inf_parser import InfParser
from edk2toolext.environment.var_dict import VarDict


class LibraryClassCheck(ICiBuildPlugin):
    """
    A CiBuildPlugin that scans the code tree and library classes for undeclared
    files

    Configuration options:
    "LibraryClassCheck": {
        IgnoreHeaderFile: [],  # Ignore a file found on disk
        IgnoreLibraryClass: [] # Ignore a declaration found in dec file
    }
    """

    def GetTestName(self, packagename: str, environment: VarDict) -> tuple:
        """ Provide the testcase name and classname for use in reporting
            testclassname: a descriptive string for the testcase can include whitespace
            classname: should be patterned <packagename>.<plugin>.<optionally any unique condition>

            Args:
              packagename: string containing name of package to build
              environment: The VarDict for the test to run in
            Returns:
                a tuple containing the testcase name and the classname
                (testcasename, classname)
        """
        return ("Check library class declarations in " + packagename, packagename + ".LibraryClassCheck")

    def __GetPkgDec(self, rootpath):
        try:
            allEntries = os.listdir(rootpath)
            for entry in allEntries:
                if entry.lower().endswith(".dec"):
                    return(os.path.join(rootpath, entry))
        except Exception:
            logging.error("Unable to find DEC for package:{0}".format(rootpath))

        return None

    ##
    # External function of plugin.  This function is used to perform the task of the MuBuild Plugin
    #
    #   - package is the edk2 path to package.  This means workspace/packagepath relative.
    #   - edk2path object configured with workspace and packages path
    #   - PkgConfig Object (dict) for the pkg
    #   - EnvConfig Object
    #   - Plugin Manager Instance
    #   - Plugin Helper Obj Instance
    #   - Junit Logger
    #   - output_stream the StringIO output stream from this plugin via logging
    def RunBuildPlugin(self, packagename, Edk2pathObj, pkgconfig, environment, PLM, PLMHelper, tc, output_stream=None):
        overall_status = 0
        LibraryClassIgnore = []

        abs_pkg_path = Edk2pathObj.GetAbsolutePathOnThisSystemFromEdk2RelativePath(packagename)
        abs_dec_path = self.__GetPkgDec(abs_pkg_path)
        wsr_dec_path = Edk2pathObj.GetEdk2RelativePathFromAbsolutePath(abs_dec_path)

        if abs_dec_path is None or wsr_dec_path == "" or not os.path.isfile(abs_dec_path):
            tc.SetSkipped()
            tc.LogStdError("No DEC file {0} in package {1}".format(abs_dec_path, abs_pkg_path))
            return -1

        # Get all include folders
        dec = DecParser()
        dec.SetBaseAbsPath(Edk2pathObj.WorkspacePath).SetPackagePaths(Edk2pathObj.PackagePathList)
        dec.ParseFile(wsr_dec_path)

        AllHeaderFiles = []

        for includepath in dec.IncludePaths:
            ## Get all header files in the library folder
            AbsLibraryIncludePath = os.path.join(abs_pkg_path, includepath, "Library")
            if(not os.path.isdir(AbsLibraryIncludePath)):
                continue

            hfiles = self.WalkDirectoryForExtension([".h"], AbsLibraryIncludePath)
            hfiles = [os.path.relpath(x,abs_pkg_path) for x in hfiles]  # make package root relative path
            hfiles = [x.replace("\\", "/") for x in hfiles]  # make package relative path

            AllHeaderFiles.extend(hfiles)

        if len(AllHeaderFiles) == 0:
            tc.SetSkipped()
            tc.LogStdError(f"No Library include folder in any Include path")
            return -1

        # Remove ignored paths
        if "IgnoreHeaderFile" in pkgconfig:
            for a in pkgconfig["IgnoreHeaderFile"]:
                try:
                    tc.LogStdOut("Ignoring Library Header File {0}".format(a))
                    AllHeaderFiles.remove(a)
                except:
                    tc.LogStdError("LibraryClassCheck.IgnoreHeaderFile -> {0} not found.  Invalid Header File".format(a))
                    logging.info("LibraryClassCheck.IgnoreHeaderFile -> {0} not found.  Invalid Header File".format(a))

        if "IgnoreLibraryClass" in pkgconfig:
            LibraryClassIgnore = pkgconfig["IgnoreLibraryClass"]


        ## Attempt to find library classes
        for lcd in dec.LibraryClasses:
            ## Check for correct file path separator
            if "\\" in lcd.path:
                tc.LogStdError("LibraryClassCheck.DecFilePathSeparator -> {0} invalid.".format(lcd.path))
                logging.error("LibraryClassCheck.DecFilePathSeparator -> {0} invalid.".format(lcd.path))
                overall_status += 1
                continue

            if lcd.name in LibraryClassIgnore:
                tc.LogStdOut("Ignoring Library Class Name {0}".format(lcd.name))
                LibraryClassIgnore.remove(lcd.name)
                continue

            logging.debug(f"Looking for Library Class {lcd.path}")
            try:
                AllHeaderFiles.remove(lcd.path)

            except ValueError:
                tc.LogStdError(f"Library {lcd.name} with path {lcd.path} not found in package filesystem")
                logging.error(f"Library {lcd.name} with path {lcd.path} not found in package filesystem")
                overall_status += 1

        ## any remaining AllHeaderFiles are not described in DEC
        for h in AllHeaderFiles:
            tc.LogStdError(f"Library Header File {h} not declared in package DEC {wsr_dec_path}")
            logging.error(f"Library Header File {h} not declared in package DEC {wsr_dec_path}")
            overall_status += 1

        ## Warn about any invalid library class names in the ignore list
        for r in LibraryClassIgnore:
            tc.LogStdError("LibraryClassCheck.IgnoreLibraryClass -> {0} not found.  Library Class not found".format(r))
            logging.info("LibraryClassCheck.IgnoreLibraryClass -> {0} not found.  Library Class not found".format(r))


        # If XML object exists, add result
        if overall_status != 0:
            tc.SetFailed("LibraryClassCheck {0} Failed.  Errors {1}".format(wsr_dec_path, overall_status), "CHECK_FAILED")
        else:
            tc.SetSuccess()
        return overall_status
