"""Module for building the control board UI specific menus"""

import logging

from menu.menu import Menu
from menu.menu_builder import MenuBuilder
from piscsi.file_cmds import FileCmds
from piscsi.piscsi_cmds import PiscsiCmds


class CtrlBoardMenuBuilder(MenuBuilder):
    """Class for building the control board UI specific menus"""

    SCSI_ID_MENU = "scsi_id_menu"
    ACTION_MENU = "action_menu"
    IMAGES_MENU = "images_menu"
    PROFILES_MENU = "profiles_menu"
    DEVICEINFO_MENU = "device_info_menu"

    ACTION_OPENACTIONMENU = "openactionmenu"
    ACTION_RETURN = "return"
    ACTION_SLOT_ATTACHINSERT = "slot_attachinsert"
    ACTION_SLOT_DETACHEJECT = "slot_detacheject"
    ACTION_SLOT_INFO = "slot_info"
    ACTION_SHUTDOWN = "shutdown"
    ACTION_LOADPROFILE = "loadprofile"
    ACTION_IMAGE_ATTACHINSERT = "image_attachinsert"

    def __init__(self, piscsi_cmd: PiscsiCmds):
        super().__init__()
        self._piscsi_client = piscsi_cmd
        self.file_cmd = FileCmds(piscsi=piscsi_cmd)

    def build(self, name: str, context_object=None) -> Menu:
        if name == CtrlBoardMenuBuilder.SCSI_ID_MENU:
            return self.create_scsi_id_list_menu(context_object)
        if name == CtrlBoardMenuBuilder.ACTION_MENU:
            return self.create_action_menu(context_object)
        if name == CtrlBoardMenuBuilder.IMAGES_MENU:
            return self.create_images_menu(context_object)
        if name == CtrlBoardMenuBuilder.PROFILES_MENU:
            return self.create_profiles_menu(context_object)
        if name == CtrlBoardMenuBuilder.DEVICEINFO_MENU:
            return self.create_device_info_menu(context_object)

        log = logging.getLogger(__name__)
        log.debug("Provided menu name [%s] cannot be built!", name)

        return self.create_scsi_id_list_menu(context_object)

    # pylint: disable=unused-argument
    def create_scsi_id_list_menu(self, context_object=None):
        """Method creates the menu displaying the 7 scsi slots"""
        devices = self._piscsi_client.list_devices()
        reserved_ids = self._piscsi_client.get_reserved_ids()

        devices_by_id = {}
        for device in devices["device_list"]:
            devices_by_id[int(device["id"])] = device

        menu = Menu(CtrlBoardMenuBuilder.SCSI_ID_MENU)

        if reserved_ids["status"] is False:
            menu.add_entry("No scsi ids reserved")

        for scsi_id in range(0, 8):
            device = None
            if devices_by_id.get(scsi_id) is not None:
                device = devices_by_id[scsi_id]
            file = "-"
            device_type = ""

            if str(scsi_id) in reserved_ids["ids"]:
                file = "[Reserved]"
            elif device is not None:
                file = str(device["file"])
                device_type = str(device["device_type"])

            menu_str = str(scsi_id) + ":"

            if device_type == "SCDP":
                menu_str += "Daynaport"
            elif device_type == "SCLP":
                menu_str += "SCSI Printer"
            elif device_type == "SCHS":
                menu_str += "Host Services"
            else:
                if file == "":
                    menu_str += "(empty)"
                else:
                    menu_str += file
                if device_type != "":
                    menu_str += " [" + device_type + "]"

            menu.add_entry(
                menu_str,
                {
                    "context": self.SCSI_ID_MENU,
                    "action": self.ACTION_OPENACTIONMENU,
                    "scsi_id": scsi_id,
                },
            )

        return menu

    # noinspection PyMethodMayBeStatic
    def create_action_menu(self, context_object=None):
        """Method creates the action submenu with action that can be performed on a scsi slot"""
        menu = Menu(CtrlBoardMenuBuilder.ACTION_MENU)
        menu.add_entry(
            "Return",
            {"context": self.ACTION_MENU, "action": self.ACTION_RETURN},
        )
        menu.add_entry(
            "Attach/Insert",
            {"context": self.ACTION_MENU, "action": self.ACTION_SLOT_ATTACHINSERT},
        )
        menu.add_entry(
            "Detach/Eject",
            {"context": self.ACTION_MENU, "action": self.ACTION_SLOT_DETACHEJECT},
        )
        menu.add_entry(
            "Info",
            {"context": self.ACTION_MENU, "action": self.ACTION_SLOT_INFO},
        )
        menu.add_entry(
            "Load Profile",
            {"context": self.ACTION_MENU, "action": self.ACTION_LOADPROFILE},
        )
        menu.add_entry(
            "Shutdown",
            {"context": self.ACTION_MENU, "action": self.ACTION_SHUTDOWN},
        )
        return menu

    def create_images_menu(self, context_object=None):
        """Creates a sub menu showing all the available images"""
        menu = Menu(CtrlBoardMenuBuilder.IMAGES_MENU)
        images_info = self._piscsi_client.list_images()
        menu.add_entry("Return", {"context": self.IMAGES_MENU, "action": self.ACTION_RETURN})
        images = images_info["files"]
        sorted_images = sorted(images, key=lambda d: d["name"])
        for image in sorted_images:
            image_str = image["name"] + " [" + image["detected_type"] + "]"
            image_context = {
                "context": self.IMAGES_MENU,
                "name": str(image["name"]),
                "device_type": str(image["detected_type"]),
                "action": self.ACTION_IMAGE_ATTACHINSERT,
            }
            menu.add_entry(image_str, image_context)
        return menu

    def create_profiles_menu(self, context_object=None):
        """Creates a sub menu showing all the available profiles"""
        menu = Menu(CtrlBoardMenuBuilder.PROFILES_MENU)
        menu.add_entry("Return", {"context": self.IMAGES_MENU, "action": self.ACTION_RETURN})
        config_files = self.file_cmd.list_config_files()
        for config_file in config_files:
            menu.add_entry(
                str(config_file),
                {
                    "context": self.PROFILES_MENU,
                    "name": str(config_file),
                    "action": self.ACTION_LOADPROFILE,
                },
            )

        return menu

    def create_device_info_menu(self, context_object=None):
        """Create a menu displaying information of an image in a scsi slot"""
        menu = Menu(CtrlBoardMenuBuilder.DEVICEINFO_MENU)
        menu.add_entry("Return", {"context": self.DEVICEINFO_MENU, "action": self.ACTION_RETURN})

        device_info = self._piscsi_client.list_devices(context_object["scsi_id"])

        if not device_info["device_list"]:
            return menu

        scsi_id = context_object["scsi_id"]
        file = device_info["device_list"][0]["file"]
        status = device_info["device_list"][0]["status"]
        if not status:
            status = "Read/Write"
        lun = device_info["device_list"][0]["unit"]
        device_type = device_info["device_list"][0]["device_type"]
        if "parameters" in device_info["device_list"][0]:
            parameters = device_info["device_list"][0]["parameters"]
        else:
            parameters = "{}"

        menu.add_entry("ID   : " + str(scsi_id))
        menu.add_entry("LUN  : " + str(lun))
        menu.add_entry("File : " + str(file))
        menu.add_entry("Type : " + str(device_type))
        menu.add_entry("R/RW : " + str(status))
        menu.add_entry("Prms : " + str(parameters))
        menu.add_entry("Vndr : " + str(device_info["device_list"][0]["vendor"]))
        menu.add_entry("Prdct: " + str(device_info["device_list"][0]["product"]))
        menu.add_entry("Rvisn: " + str(device_info["device_list"][0]["revision"]))
        menu.add_entry("Blksz: " + str(device_info["device_list"][0]["block_size"]))
        menu.add_entry("Imgsz: " + str(device_info["device_list"][0]["size"]))

        return menu

    def get_piscsi_client(self):
        """Returns an instance of the piscsi client"""
        return self._piscsi_client
