from enum import Enum
from typing import List
from import_script_status_codes_translator import ImportScriptStatusCodeTranslator
from logger_wrapper import LoggerWrapper


class EMExportVersion(Enum):
    """
    A class the holds the supported EM Export versions.
    """
    em_import_script_version = '9.0.27.083'

    @staticmethod
    def get_tar_members_based_on_em_export_version(em_export_version: str) -> List[str]:
        """
        The following static method return the required EM Export TAR content based on the input export version.
        """
        # set the expected tar content per version:
        v1_tar_members = [
            # EM util types:
            EMUtilType.USER, EMUtilType.DC, EMUtilType.SYS, EMUtilType.STATISTICS, EMUtilType.DEF,
            EMUtilType.GC, EMUtilType.CAL, EMUtilType.COLLECT, EMUtilType.FILTER, EMUtilType.VIEW,
            EMUtilType.HIER, EMUtilType.WORKLOAD,
            # TAR content files:
            EMTarContent.EM_EXPORT_FOR_SAAS_MAIN_DIR,
            EMTarContent.EXPORT_SCRIPT_VERSION,
            EMTarContent.EM_VERSION,
            EMTarContent.DB_ENC_KEY, EMTarContent.CHECKSUM, EMTarContent.DATA_DIR
        ]

        future_tar_members = [
            # Additional EM util types:
            EMUtilType.ALERT, EMUtilType.MAINT, EMUtilType.REPORT,
            EMUtilType.AUDIT,
            EMUtilType.MFT, EMUtilType.BIM_FORECAST, EMUtilType.HISTORY,
            EMUtilType.EXPORT_FORCAST_HISTORY, EMUtilType.EXPORT_WCM, EMUtilType.NET
        ]

        tar_members = v1_tar_members
        return EMExportVersion.arrange_tar_content(tar_content=tar_members)

    @staticmethod
    def arrange_tar_content(tar_content: List[Enum]) -> List:
        """
        Arrange the tar content with the full directories and files prefix
        like it should appear in the tar file
        """
        main_tar_dir_prefix = EMTarContent.get_main_tar_dir_prefix()
        data_dir_prefix = EMTarContent.get_data_dir_prefix(main_tar_dir_prefix=main_tar_dir_prefix)
        arranged_tar_content = []
        for content in tar_content:
            if type(content) == EMUtilType:
                arranged_tar_content.append(data_dir_prefix + content.value)
            elif type(content) == EMTarContent and content.value != EMTarContent.EM_EXPORT_FOR_SAAS_MAIN_DIR.value:
                arranged_tar_content.append(main_tar_dir_prefix + content.value)

        return arranged_tar_content


class EMUtilType(Enum):
    """
    A class that holds all the supported EM UTIL types for all EM Export versions.
    """
    USER = "user.exp"
    DC = "dc.exp"
    SYS = "sys.exp"
    STATISTICS = "statistics.exp"
    DEF = "def.exp"
    GC = "gc.exp"
    CAL = "cal.exp"
    COLLECT = "collect.exp"
    FILTER = "filter.exp"
    VIEW = "view.exp"
    HIER = "hier.exp"
    WORKLOAD = "workload.exp"
    ALERT = "alert.exp"
    MAINT = "maint.exp"
    REPORT = "report.exp"
    AUDIT = "audit.exp"
    MFT = "mft.exp"
    BIM_FORECAST = "bim_forecast.exp"
    HISTORY = "history.exp"
    EXPORT_FORCAST_HISTORY = "ExportForcastHistory.exp"
    EXPORT_WCM = "ExportWCM.exp"
    NET = "Net_*.exp"

    @staticmethod
    def get_string_value_for_enum(em_util_type: Enum) -> str:
        """
        Return the filename string value of input EMUtilType Enum.
        """
        for e in EMUtilType:
            if e == em_util_type:
                return e.file_name

    @staticmethod
    def concat_two_enum_type_lists(v1_em_types: List[Enum], v2_em_types: List[Enum]) -> List[str]:
        """
        Concat two enum types list to a list of strings with the string value
        of each enum from both input list.
        """
        return [type.value for type in v1_em_types] + [type.value for type in v2_em_types]


class EMTarContent(Enum):
    """
    A class that holds the TAR file content files for all EM Export versions.
    """
    EM_EXPORT_FOR_SAAS_MAIN_DIR = 'EMExportForSaaS'
    EXPORT_SCRIPT_VERSION = 'ExportScriptVersion.txt'
    EM_VERSION = 'em_version.txt'
    DB_ENC_KEY = 'temp_onprem.txt_exp'
    CHECKSUM = 'checksum.txt'
    DATA_DIR = 'data'
    TAR_SEP = '/'

    @staticmethod
    def get_main_tar_dir_prefix() -> str:
        return f"{EMTarContent.EM_EXPORT_FOR_SAAS_MAIN_DIR.value}{EMTarContent.TAR_SEP.value}"

    @staticmethod
    def get_data_dir_prefix(main_tar_dir_prefix: str) -> str:
        if main_tar_dir_prefix:
            return f"{main_tar_dir_prefix}{EMTarContent.DATA_DIR.value}{EMTarContent.TAR_SEP.value}"
        else:
            return f"{EMTarContent.get_main_tar_dir_prefix()}{EMTarContent.DATA_DIR.value}{EMTarContent.TAR_SEP.value}"


class PackageTarContent(Enum):
    """
    A class that holds the structure of a "ctm-package" TAR that bundles together an EM
    export and one or more CTM (Control-M/Server) exports.

    Expected layout of a package TAR file is as follows:

        ctm-package/
            ├── em/
            │   └── EMExportForSaaS.tar.gz
            └── servers/
                ├── ctmName/
                ├── ctmName2/
                └── .../
    """
    EM_DIR = 'em'
    SERVERS_DIR = 'servers'
    TAR_SEP = '/'

    @staticmethod
    def get_em_dir_prefix() -> str:
        """
        Return the expected prefix of the EM folder inside the package TAR
        (e.g. ``em/``).
        """
        return f"{PackageTarContent.EM_DIR.value}{PackageTarContent.TAR_SEP.value}"

    @staticmethod
    def get_servers_dir_prefix() -> str:
        """
        Return the expected prefix of the servers folder inside the package TAR
        (e.g. ``servers/``).
        """
        return f"{PackageTarContent.SERVERS_DIR.value}{PackageTarContent.TAR_SEP.value}"

    @staticmethod
    def is_inner_tar_name(name: str) -> bool:
        """
        Return True if the given member name ends with the supported inner TAR
        extension (``.tar.gz``).
        """
        if not name:
            return False
        return name.lower().endswith('.tar.gz')
