"""Part of the Mission Operation Database Exporter for the EVIE project.
Event exporter.
"""
import datetime
import logging
import time
import os
from pathlib import Path

from fsfwgen.events.event_parser import (
    handle_csv_export,
    handle_cpp_export,
    SubsystemDefinitionParser,
    EventParser,
    EventDictT,
)
from fsfwgen.parserbase.file_list_parser import FileListParser
from fsfwgen.utility.printer import PrettyPrinter
from fsfwgen.utility.file_management import copy_file
from definitions import BspType, ROOT_DIR, OBSW_ROOT_DIR

_LOGGER = logging.getLogger(__name__)
DATE_TODAY = datetime.datetime.now()
DATE_STRING_FULL = DATE_TODAY.strftime("%Y-%m-%d %H:%M:%S")

PRINT_EVENTS = False
PRINT_SUBSYSTEM_TABLE = False
EXPORT_SUBSYSTEM_TABLE = True

GENERATE_CPP = True
GENERATE_CPP_H = True
GENERATE_CSV = True
COPY_CPP_FILE = True
COPY_CPP_H_FILE = True
MOVE_CSV_FILE = True

PARSE_HOST_BSP = True

# Store these files relative to the events folder
CPP_FILENAME = Path(
    f"{os.path.dirname(os.path.realpath(__file__))}/translateEvents.cpp"
)
CPP_H_FILENAME = Path(
    f"{os.path.dirname(os.path.realpath(__file__))}/translateEvents.h"
)

FILE_SEPARATOR = ";"


class BspConfig:
    def __init__(self, bsp_select: BspType):
        self.bsp_select = bsp_select
        self.bsp_dir_name = self.bsp_select.value

        # Store this file in the root of the generators folder
        self.csv_filename = Path(f"{ROOT_DIR}/{self.bsp_dir_name}_events.csv")
        self.subsystems_csv_filename = Path(
            f"{ROOT_DIR}/{self.bsp_dir_name}_subsystems.csv"
        )
        self.csv_copy_dest = Path(f"{OBSW_ROOT_DIR}/tmtc/eive_tmtc/config/events.csv")
        self.subsystem_csv_copy_dest = Path(
            f"{OBSW_ROOT_DIR}/tmtc/eive_tmtc/config/subsystems.csv"
        )

        if (
            self.bsp_select == BspType.BSP_Q7S
            or self.bsp_select == BspType.BSP_LINUX_BOARD
        ):
            self.fsfw_config_root = Path(f"{OBSW_ROOT_DIR}/linux/fsfwconfig")

        else:
            self.fsfw_config_root = Path(
                f"{OBSW_ROOT_DIR}/{self.bsp_dir_name}/fsfwconfig"
            )

        self.cpp_copy_dest = Path(f"{self.fsfw_config_root}/events/")

        self.subystem_defs_destinations = [
            f"{self.fsfw_config_root}/events/subsystemIdRanges.h",
            f"{OBSW_ROOT_DIR}/fsfw/src/fsfw/events/fwSubsystemIdRanges.h",
            f"{OBSW_ROOT_DIR}/common/config/eive/eventSubsystemIds.h",
        ]

        self.header_defs_destinations = [
            f"{OBSW_ROOT_DIR}/mission/",
            f"{OBSW_ROOT_DIR}/fsfw/",
            f"{self.fsfw_config_root}",
            f"{OBSW_ROOT_DIR}/test/",
            f"{OBSW_ROOT_DIR}/bsp_q7s/",
            f"{OBSW_ROOT_DIR}/linux/",
        ]

    def subsystem_defs_as_paths(self):
        return [Path(x) for x in self.subystem_defs_destinations]

    def header_defs_as_paths(self):
        return [Path(x) for x in self.header_defs_destinations]


def parse_events(
    bsp_type: BspType,
    generate_csv: bool,
    generate_cpp: bool,
    copy_csv_to_eive_tmtc: bool,
):
    bsp_cfg = BspConfig(bsp_type)
    _LOGGER.info(f"EventParser: Parsing events for {bsp_type.name}")
    # Small delay for clean printout
    time.sleep(0.01)
    event_list = generate_event_list(bsp_cfg, copy_csv_to_eive_tmtc)
    if PRINT_EVENTS:
        PrettyPrinter.pprint(event_list)
        # Delay for clean printout
        time.sleep(0.1)
    if generate_csv:
        handle_csv_export(
            file_name=bsp_cfg.csv_filename,
            event_list=event_list,
            file_separator=FILE_SEPARATOR,
        )
        if copy_csv_to_eive_tmtc:
            _LOGGER.info(f"Copying CSV file to {bsp_cfg.cpp_copy_dest}")
            copy_file(
                filename=bsp_cfg.csv_filename,
                destination=bsp_cfg.csv_copy_dest,
                delete_existing_file=True,
            )

    if generate_cpp:
        handle_cpp_export(
            event_list=event_list,
            date_string=DATE_STRING_FULL,
            file_name=CPP_FILENAME,
            generate_header=GENERATE_CPP_H,
            header_file_name=CPP_H_FILENAME,
        )
        if COPY_CPP_FILE:
            _LOGGER.info(
                f"EventParser: Copying CPP translation file to {bsp_cfg.cpp_copy_dest}"
            )
            copy_file(CPP_FILENAME, bsp_cfg.cpp_copy_dest)
            copy_file(CPP_H_FILENAME, bsp_cfg.cpp_copy_dest)
    _LOGGER.info(f"Parsing done for {bsp_type.name}")


def generate_event_list(cfg: BspConfig, copy_csv_to_eive_tmtc: bool) -> EventDictT:
    subsystem_parser = SubsystemDefinitionParser(cfg.subsystem_defs_as_paths())
    subsystem_table = subsystem_parser.parse_files()
    _LOGGER.info(f"Found {len(subsystem_table)} subsystem definitions.")
    if PRINT_SUBSYSTEM_TABLE:
        PrettyPrinter.pprint(subsystem_table)
    if EXPORT_SUBSYSTEM_TABLE:
        PrettyPrinter.pprint(subsystem_table)
        with open(cfg.subsystems_csv_filename, "w") as file:
            for name_str, table_entry in subsystem_table.items():
                subsystem_id = int(table_entry[0])
                file.write(f"{subsystem_id}{FILE_SEPARATOR}{name_str}\n")
        if copy_csv_to_eive_tmtc:
            _LOGGER.info(f"Copying CSV file to {cfg.cpp_copy_dest}")
            copy_file(
                filename=cfg.subsystems_csv_filename,
                destination=cfg.subsystem_csv_copy_dest,
                delete_existing_file=True,
            )

    event_header_parser = FileListParser(cfg.header_defs_as_paths())
    event_headers = event_header_parser.parse_header_files(
        True, "Parsing event header file list:\n", True
    )
    # PrettyPrinter.pprint(event_headers)
    # myEventList = parseHeaderFiles(subsystem_table, event_headers)
    event_parser = EventParser(event_headers, subsystem_table)
    event_parser.obsw_root_path = OBSW_ROOT_DIR
    event_parser.set_moving_window_mode(moving_window_size=7)
    event_table = event_parser.parse_files()
    events_sorted = dict(sorted(event_table.items()))
    _LOGGER.info(f"Found {len(events_sorted)} entries")
    return events_sorted