# V2.1.1d Beta
import traceback
from customtkinter import CTkFrame, CTk, CTkButton, CTkLabel, CTkImage, CTkEntry, CTkScrollableFrame, CTkProgressBar
from PIL import Image
import tkinter as tk

from shared.utils import Logger
from .custom_elements import OptionMenu

# =============== Validator Validator View ===============
class ValidatorValidatorView(CTkFrame):
    """Contains the elements of the user login interface."""
    def __init__(self, master,
            template: dict[str, str],
            images: dict[str, str],
            kit_version: str,
            width = 200, height = 200, 
            corner_radius = None, border_width = None, 
            bg_color = "transparent", fg_color = None, 
            border_color = None, background_corner_colors = None, 
            overwrite_preferred_drawing_method = None, **kwargs):
        super().__init__(master, 
            width, height, 
            corner_radius, border_width, 
            bg_color, fg_color, 
            border_color, background_corner_colors, 
            overwrite_preferred_drawing_method, **kwargs)
        
        # Logger 
        self.logger = Logger.create_logger(logger_name = "Validator Validator View", log_file_name = "validator_app")

        # Master
        self.master: CTk = master
        
        # Template and images
        self.template: dict[str, str] = template
        self.images: dict[str, str] = images
        self.kitVersion = kit_version
        
        # Creates the view
        self.setup_view()
        
    # ========== Setup View ==========
    def setup_view(self):
        """Create the widgets, set template and window title."""
        try:
            # ===== Window Title =====
            self.master.title(self.template["WindowTitle"])
            # ========================
            
            # ===== Login Main Frame =====
            self.configure(**self.template["MainFrame"])
            self.pack(anchor = "center", padx = (0, 0), pady = (0, 0))
            self.pack_propagate(False)
            # ============================
            
            # ===== Sidenavbar Widgets =====
            self.sidenavbarFrame = CTkFrame(
                master = self,
                **self.template["PermanentElements"]["Sidenavbar"]["Frame"]
            )
            
            self.sidenavbarTitleLabel = CTkLabel(
                master = self.sidenavbarFrame,
                **self.template_processing(template = self.template["PermanentElements"]["Sidenavbar"]["TitleLabel"])
            )
            
            self.sidenavbarSeparator = CTkFrame(
                master = self.sidenavbarFrame,
                **self.template["PermanentElements"]["Sidenavbar"]["Separator"]
            )
            
            self.sidenavbarValidationTabButton = CTkButton(
                master = self.sidenavbarFrame,
                **self.template["PermanentElements"]["Sidenavbar"]["ValidationTabButton"]
            )
            
            self.sidenavbarRaportTabButton = CTkButton(
                master = self.sidenavbarFrame,
                **self.template["PermanentElements"]["Sidenavbar"]["RaportTabButton"]
            )
            
            self.sidenavbarNewsTabButton = CTkButton(
                master = self.sidenavbarFrame,
                **self.template["PermanentElements"]["Sidenavbar"]["NewsTabButton"]
            )
            
            self.sidenavbarPackagesTabButton = CTkButton(
                master = self.sidenavbarFrame,
                **self.template["PermanentElements"]["Sidenavbar"]["PackagesTabButton"]
            )
            
            self.sidenavbarKitsTabButton = CTkButton(
                master = self.sidenavbarFrame,
                **self.template["PermanentElements"]["Sidenavbar"]["KitsTabButton"]
            )
            
            self.sidenavbarTesterButton = CTkButton(
                master = self.sidenavbarFrame,
                **self.template["PermanentElements"]["Sidenavbar"]["TestButton"]
            )
            
            self.sidenavbarSupportButton = CTkButton(
                master = self.sidenavbarFrame,
                **self.template["PermanentElements"]["Sidenavbar"]["SupportButton"]
            )
            
            self.sidenavbarLogoutButton = CTkButton(
                master = self.sidenavbarFrame,
                **self.template["PermanentElements"]["Sidenavbar"]["LogoutButton"]
            )
            # ==============================
            
            # ===== Banner Image =====
            self.bannerImageFrame = CTkFrame(
                master = self,
                **self.template["PermanentElements"]["BannerImage"]["Frame"]
            )
            
            image = Image.open(self.images["validation"])
            bannerImage = CTkImage(
                light_image = image, dark_image = image, 
                size = (1024*0.5, 110*0.5))
            bannerImageLabel = CTkLabel(master = self.bannerImageFrame, text = "", image = bannerImage)
            # ========================
            
            # ===== Tabs Frame =====
            self.tabFrame = CTkFrame(
                master = self,
                **self.template["PermanentElements"]["TabFrame"]["Frame"]
            )
            # ======================
            
            # ===== Footer Widgets =====
            self.footerFrame = CTkFrame(
                master = self,
                **self.template["PermanentElements"]["FooterFrame"]["Frame"]
            )
            self.footerVersionLabel = CTkLabel(
                master = self.footerFrame,
                text = f"Kit Validare V{self.kitVersion} Stabila",
                **self.template_processing(template = self.template["PermanentElements"]["FooterFrame"]["InterfaceVersion"])
            )
            # ==========================
            
            # ===== Placement =====
            # Sidenavbar
            self.sidenavbarFrame.pack(anchor = "center", side = "left", padx = (5, 5), pady = (5, 5))
            self.sidenavbarFrame.pack_propagate(False)
            self.sidenavbarTitleLabel.pack(anchor = "center", padx = (0, 0), pady = (20, 20))
            self.sidenavbarSeparator.pack(anchor = "center", padx = (0, 0), pady = (0, 5))
            
            self.sidenavbarValidationTabButton.pack(anchor = "center", padx = (0, 0), pady = (0, 5))
            self.sidenavbarRaportTabButton.pack(anchor = "center", padx = (0, 0), pady = (0, 5))
            self.sidenavbarNewsTabButton.pack(anchor = "center", padx = (0, 0), pady = (0, 5))
            self.sidenavbarPackagesTabButton.pack(anchor = "center", padx = (0, 0), pady = (0, 5))
            self.sidenavbarKitsTabButton.pack(anchor = "center", padx = (0, 0), pady = (0, 5))
            
            self.sidenavbarLogoutButton.pack(anchor = "center", side = "bottom", padx = (0, 0), pady = (5, 5))
            self.sidenavbarSupportButton.pack(anchor = "center", side = "bottom", padx = (0, 0), pady = (5, 0))
            # Banner Image
            self.bannerImageFrame.pack(anchor = "center", side = "top", padx = (0, 5), pady = (5, 5))
            self.bannerImageFrame.pack_propagate(False)
            bannerImageLabel.pack(anchor = "center", padx = (0, 0), pady = (0, 0), expand = True)
            # Tab Frame
            self.tabFrame.pack(anchor = "center", side = "top", padx = (0, 5), pady = (0, 5))
            self.tabFrame.pack_propagate(False)
            # Footer Frame
            self.footerFrame.pack(anchor = "center", side = "top", padx = (0, 5), pady = (0, 5))
            self.footerFrame.pack_propagate(False)
            self.footerVersionLabel.pack(anchor = "center", side = "left", padx = (6, 0))
            # =====================
        except:
            traceBack = traceback.format_exc()
            self.logger.error(
                f"[{self.__class__.__name__} - {self.setup_view.__name__}] "
                f"Failed to create the login view. \n{traceBack}")
    # ================================
    
    # ========== Validator Tabs ==========
    def create_validation_tab(self):
        """Create the validation tab."""
        try:
            # ===== Main Frame =====
            self.ValidationTabMainFrame = CTkFrame(
                master = self.tabFrame,
                **self.template["ValidationTab"]["MainFrame"]
            )
            self.ValidationTabMainFrame.pack(anchor = "center", padx = (0, 0), pady = (0, 0))
            self.ValidationTabMainFrame.pack_propagate(False)
            # ======================
            
            # ===== Choose Frame =====
            self.validationTabChooseFrame = CTkFrame(
                master = self.ValidationTabMainFrame,
                **self.template["ValidationTab"]["ChooseFrame"]["Frame"]
            )
            self.validationTabChooseEntry = CTkEntry(
                master = self.validationTabChooseFrame,
                **self.template_processing(template = self.template["ValidationTab"]["ChooseFrame"]["Entrybox"])
            )
            self.validationTabChooseButton = CTkButton(
                master = self.validationTabChooseFrame,
                **self.template["ValidationTab"]["ChooseFrame"]["Button"]
            )
            # ========================
            
            # ===== Verify Frame =====
            self.validationTabVerifyFrame = CTkFrame(
                master = self.ValidationTabMainFrame,
                **self.template["ValidationTab"]["VerifyFrame"]["Frame"]
            )
            self.validationTabVerifyButtonVerify = CTkButton(
                master = self.validationTabVerifyFrame,
                **self.template["ValidationTab"]["VerifyFrame"]["ButtonVerify"]
            )
            self.validationTabVerifyButtonUpdate = CTkButton(
                master = self.validationTabVerifyFrame,
                **self.template["ValidationTab"]["VerifyFrame"]["ButtonUpdate"]
            )
            self.validationTabVerifyScrollFrame = CTkScrollableFrame(
                master = self.validationTabVerifyFrame,
                **self.template["ValidationTab"]["VerifyFrame"]["ScrollFrame"]
            )
            # ========================
            
            # ===== Validate Frame =====
            self.validationTabValidateFrame = CTkFrame(
                master = self.ValidationTabMainFrame,
                **self.template["ValidationTab"]["ValidateFrame"]["Frame"]
            )
            
            self.validationTabValidateLeftSection = CTkFrame(
                self.validationTabValidateFrame,
                **self.template["ValidationTab"]["ValidateFrame"]["SideTabs"])
            
            self.validationTabValidateRightSection = CTkFrame(
                self.validationTabValidateFrame,
                **self.template["ValidationTab"]["ValidateFrame"]["SideTabs"])
            
            
            self.validationTabValidateScrollFrame = CTkScrollableFrame(
                master = self.validationTabValidateLeftSection,
                **self.template["ValidationTab"]["ValidateFrame"]["ScrollFrame"]
            )
            self.validationTabProgressBar = CTkProgressBar(
                master = self.validationTabValidateLeftSection,
                **self.template["ValidationTab"]["ValidateFrame"]["Progressbar"]
            )
            
            self.validationTabValidateButton = CTkButton(
                master = self.validationTabValidateRightSection,
                **self.template["ValidationTab"]["ValidateFrame"]["Button"]
            )
            iconDropDown = CTkImage(Image.open(self.images["down_arrow"]), size=(20, 20))
            self.validationTabValidateOptionMenu = OptionMenu(
                master = self.validationTabValidateRightSection,
                values = ["---"],
                anchor = "center",
                **self.template_processing(template = self.template["ValidationTab"]["ValidateFrame"]["OptionMenu"])
            )
            self.validationTabValidateOptionMenu.setDropdownIcon(iconDropDown)
            # ==========================
            
            # ===== Save Raport Frame =====
            self.validationTabSaveRaportFrame = CTkFrame(
                master = self.ValidationTabMainFrame,
                **self.template["ValidationTab"]["DownloadFrame"]["Frame"]
            )
            self.validationTabSaveRaportEntry = CTkEntry(
                master = self.validationTabSaveRaportFrame,
                **self.template_processing(template = self.template["ValidationTab"]["DownloadFrame"]["Entrybox"])
            )
            self.validationTabSaveRaportButton = CTkButton(
                master = self.validationTabSaveRaportFrame,
                **self.template["ValidationTab"]["DownloadFrame"]["Button"]
            )
            # =============================
            
            # ===== Placement =====
            # Choose Frame
            self.validationTabChooseFrame.pack(anchor = "center", side = "top", padx = (0, 0), pady = (0, 0))
            self.validationTabChooseFrame.pack_propagate(False)
            self.validationTabChooseEntry.pack(anchor = "center", side = "left", padx = (5, 5), pady = (0, 0))
            self.validationTabChooseButton.pack(anchor = "center", side = "left", padx = (0, 0), pady = (0, 0))
            # Verify Frame
            self.validationTabVerifyFrame.pack(anchor = "center", side = "top", padx = (0, 0), pady = (5, 0))
            self.validationTabVerifyFrame.pack_propagate(False)
            self.validationTabVerifyScrollFrame.pack(anchor = "center", side = "left", padx = (5, 5), pady = (5, 5))
            self.validationTabVerifyButtonVerify.pack(anchor = "center", side = "top", padx = (0, 0), pady = (5, 0))
            self.validationTabVerifyButtonUpdate.pack(anchor = "center", side = "top", padx = (0, 0), pady = (5, 0))
            # Validate Frame
            self.validationTabValidateFrame.pack(anchor="center", side="top", padx=0, pady=(5, 0))
            self.validationTabValidateFrame.pack_propagate(False)
            self.validationTabValidateLeftSection.pack(side="left", fill="both", expand = True, padx = 5, pady = 5)
            self.validationTabValidateLeftSection.pack_propagate(False)
            self.validationTabValidateRightSection.pack(anchor="center", side="top", padx = 5, pady = 5)
            self.validationTabValidateRightSection.pack_propagate(True)
            self.validationTabProgressBar.pack(anchor="center", side="bottom", padx=(0, 0), pady=(0, 0))
            self.validationTabValidateScrollFrame.pack(anchor="center", side="top", padx=(0, 0), pady=(0, 5))
            self.validationTabValidateButton.pack(anchor="center", side="top", padx=0, pady=(0, 0))
            self.validationTabValidateOptionMenu.pack(anchor="center", side="top", padx=0, pady=(5, 0))
            # Raport Frame
            self.validationTabSaveRaportFrame.pack(anchor = "center", side = "top", padx = (0, 0), pady = (5, 0))
            self.validationTabSaveRaportFrame.pack_propagate(False)
            self.validationTabSaveRaportEntry.pack(anchor = "center", side = "left", padx = (5, 5), pady = (0, 0))
            self.validationTabSaveRaportButton.pack(anchor = "center", side = "left", padx = (0, 0), pady = (0, 0))
            # =====================
        except:
            traceBack = traceback.format_exc()
            self.logger.error(
                f"[{self.__class__.__name__} - {self.create_validation_tab.__name__}] "
                f"Failed to create the validation tab. \n{traceBack}")
    
    def create_raports_tab(self):
        """Create the raports tab."""
        try:
            # ===== Main Frame =====
            self.RaportTabMainFrame = CTkFrame(
                master = self.tabFrame,
                **self.template["RaportTab"]["MainFrame"]
            )
            # ======================
            
            # ===== Title Frame =====
            self.RaportTabTitleFrame = CTkFrame(
                master = self.RaportTabMainFrame,
                **self.template["RaportTab"]["Title"]["Frame"]
            )
            
            self.RaportTabTitleLabel = CTkLabel(
                master = self.RaportTabTitleFrame,
                **self.template_processing(self.template["RaportTab"]["Title"]["Label"])
            )
            # =======================
            
            # ===== Raports Scrollframe =====
            self.RaportTabScrollframe = CTkScrollableFrame(
                master = self.RaportTabMainFrame,
                **self.template["RaportTab"]["Raports"]["ScrollFrame"]
            )
            # ===============================
            
            # ===== Widget Placement =====
            self.RaportTabMainFrame.pack(anchor = "center", padx = (0, 0), pady = (0, 0))
            self.RaportTabMainFrame.pack_propagate(False)
            self.RaportTabTitleFrame.pack(anchor = "center", side = "top", padx = (0, 0), pady = (0, 0))
            self.RaportTabTitleFrame.pack_propagate(False)
            self.RaportTabTitleLabel.pack(anchor = "center", expand = True, padx = (0, 0), pady = (0, 0))
            self.RaportTabScrollframe.pack(anchor = "center", side = "top", padx = (0, 0), pady = (5, 0))
            # ============================
        except:
            traceBack = traceback.format_exc()
            self.logger.error(
                f"[{self.__class__.__name__} - {self.create_validation_tab.__name__}] "
                f"Failed to create the raports tab. \n{traceBack}")
    
    def create_news_tab(self):
        """Create the news tab."""
        try:
            # ===== Main Frame =====
            self.NewsTabMainFrame = CTkFrame(
                master = self.tabFrame,
                **self.template["NewsTab"]["MainFrame"]
            )
            
            # ======================
            
            # ===== Title Frame =====
            self.NewsTabTitleFrame = CTkFrame(
                master = self.NewsTabMainFrame,
                **self.template["NewsTab"]["Title"]["Frame"]
            )
            
            self.NewsTabTitleLabel = CTkLabel(
                master = self.NewsTabTitleFrame,
                **self.template_processing(self.template["NewsTab"]["Title"]["Label"])
            )
            # =======================
            
            # ===== Raports Scrollframe =====
            self.NewsTabScrollframe = CTkScrollableFrame(
                master = self.NewsTabMainFrame,
                **self.template["NewsTab"]["News"]["ScrollFrame"]
            )
            # ===============================
            
            # ===== Widget Placement =====
            self.NewsTabMainFrame.pack(anchor = "center", padx = (0, 0), pady = (0, 0))
            self.NewsTabMainFrame.pack_propagate(False)
            self.NewsTabTitleFrame.pack(anchor = "center", side = "top", padx = (0, 0), pady = (0, 0))
            self.NewsTabTitleFrame.pack_propagate(False)
            self.NewsTabTitleLabel.pack(anchor = "center", expand = True, padx = (0, 0), pady = (0, 0))
            self.NewsTabScrollframe.pack(anchor = "center", side = "top", padx = (0, 0), pady = (5, 0))
            # ============================
        except:
            traceBack = traceback.format_exc()
            self.logger.error(
                f"[{self.__class__.__name__} - {self.create_news_tab.__name__}] "
                f"Failed to create the news tab. \n{traceBack}")
    
    def create_packages_tab(self):
        """Create the packages tab."""
        try:
            # ===== Main Frame =====
            self.PackagesTabMainFrame = CTkFrame(
                master = self.tabFrame,
                **self.template["PackagesTab"]["MainFrame"]
            )
            # ======================
            
            # ===== Title Frame =====
            self.PackagesTabTitleFrame = CTkFrame(
                master = self.PackagesTabMainFrame,
                **self.template["PackagesTab"]["Title"]["Frame"]
            )
            
            self.PackagesTabTitleLabel = CTkLabel(
                master = self.PackagesTabTitleFrame,
                **self.template_processing(self.template["PackagesTab"]["Title"]["Label"])
            )
            # =======================
            
            # ===== Raports Scrollframe =====
            self.PackagesTabScrollframe = CTkScrollableFrame(
                master = self.PackagesTabMainFrame,
                **self.template["PackagesTab"]["Packages"]["ScrollFrame"]
            )
            # ===============================
            
            # ===== Widget Placement =====
            self.PackagesTabMainFrame.pack(anchor = "center", padx = (0, 0), pady = (0, 0))
            self.PackagesTabMainFrame.pack_propagate(False)
            self.PackagesTabTitleFrame.pack(anchor = "center", side = "top", padx = (0, 0), pady = (0, 0))
            self.PackagesTabTitleFrame.pack_propagate(False)
            self.PackagesTabTitleLabel.pack(anchor = "center", expand = True, padx = (0, 0), pady = (0, 0))
            self.PackagesTabScrollframe.pack(anchor = "center", side = "top", padx = (0, 0), pady = (5, 0))
            # ============================
            
        except:
            traceBack = traceback.format_exc()
            self.logger.error(
                f"[{self.__class__.__name__} - {self.create_packages_tab.__name__}] "
                f"Failed to create the packages tab. \n{traceBack}")
    
    def create_kits_tab(self):
        """Create the kits tab."""
        try:
            # ===== Main Frame =====
            self.KitsTabMainFrame = CTkFrame(
                master = self.tabFrame,
                **self.template["KitsTab"]["MainFrame"]
            )
            self.KitsTabMainFrame.pack(anchor = "center", padx = (0, 0), pady = (0, 0))
            self.KitsTabMainFrame.pack_propagate(False)
            # ======================
            
            # ===== Title Frame =====
            self.KitsTabTitleFrame = CTkFrame(
                master = self.KitsTabMainFrame,
                **self.template["KitsTab"]["Title"]["Frame"]
            )
            
            self.KitsTabTitleLabel = CTkLabel(
                master = self.KitsTabTitleFrame,
                **self.template_processing(self.template["KitsTab"]["Title"]["Label"])
            )
            # =======================
            
            # ===== Raports Scrollframe =====
            self.KitsTabScrollframe = CTkScrollableFrame(
                master = self.KitsTabMainFrame,
                **self.template["KitsTab"]["Kits"]["ScrollFrame"]
            )
            # ===============================
            
            # ===== Widget Placement =====
            self.KitsTabMainFrame.pack(anchor = "center", padx = (0, 0), pady = (0, 0))
            self.KitsTabMainFrame.pack_propagate(False)
            self.KitsTabTitleFrame.pack(anchor = "center", side = "top", padx = (0, 0), pady = (0, 0))
            self.KitsTabTitleFrame.pack_propagate(False)
            self.KitsTabTitleLabel.pack(anchor = "center", expand = True, padx = (0, 0), pady = (0, 0))
            self.KitsTabScrollframe.pack(anchor = "center", side = "top", padx = (0, 0), pady = (5, 0))
            # ============================
        except:
            traceBack = traceback.format_exc()
            self.logger.error(
                f"[{self.__class__.__name__} - {self.create_kits_tab.__name__}] "
                f"Failed to create the kits tab. \n{traceBack}")
    # ====================================
    
    # ========== Template Helpers ==========
    def template_processing(self, template: dict[str, str]) -> dict[str, str]:
        """Process template to fix certain aspects."""
        try:
            templateFix = template.copy()
            if "font" in templateFix and isinstance(templateFix["font"], list):
                templateFix["font"] = tuple(templateFix["font"])
            if "dropdown_font" in templateFix and isinstance(templateFix["dropdown_font"], list):
                templateFix["dropdown_font"] = tuple(templateFix["dropdown_font"])
                
            return templateFix
        except:
            traceBack = traceback.format_exc()
            self.logger.error(
                f"[{self.__class__.__name__} - {self.template_processing.__name__}] "
                f"Failed to process template. \n{traceBack}")
    
    def place_tester_button(self, command) -> None:
        """If the user is a tester it places this button."""
        try:
            self.sidenavbarTesterButton = CTkButton(
                master = self.sidenavbarFrame,
                **self.template["PermanentElements"]["Sidenavbar"]["TestButton"],
                command = command
            )
            self.sidenavbarTesterButton.pack(anchor = "center", side = "bottom", padx = (0, 0), pady = (0, 0))
        except Exception as e:
            traceBack = traceback.format_exc()
            self.logger.error(
                f"[{self.__class__.__name__} - {self._font_fix.__name__}] "
                f"Failed to place the tester button. \n{traceBack}")
    # ======================================
# ========================================================