import pickle
from tkinter import Frame, Canvas, NW
from typing import Any, Dict, Optional
from PIL import Image, ImageTk
from pathlib import Path


class MyPlot(Frame):
    """
    A custom plot widget that displays images in a Frame with blinking capability.
    
    This class creates a plot display widget that can show images and supports blinking
    between two different images. It uses a Canvas widget for image display and can
    load additional data from pickle files for blinking functionality.
    
    Attributes:
        width (int): Width of the plot display area
        height (int): Height of the plot display area
        image (Optional[PhotoImage]): The current image being displayed
        image1 (Optional[PhotoImage]): First image for blinking
        image2 (Optional[PhotoImage]): Second image for blinking
        canvas (Canvas): The Canvas widget for image display
        string1 (Optional[Any]): Additional data loaded from first pickle file
        string2 (Optional[Any]): Additional data loaded from second pickle file
    """

    def __init__(
        self,
        parent: Any,
        row: int,
        column: int,
        width: int,
        height: int,
        path_default: Path,
        columnspan: int = 2,
        rowspan: int = 1,
        **kwargs: Dict[str, Any]
    ) -> None:
        """
        Initialize the MyPlot widget.

        Args:
            parent: The parent widget
            row: Row position in the parent's grid
            column: Column position in the parent's grid
            width: Width of the plot display area
            height: Height of the plot display area
            path_default: Base path for finding the test image file
            columnspan: Number of columns the widget should span
            rowspan: Number of rows the widget should span
            **kwargs: Additional keyword arguments passed to the Frame widget
        """
        super().__init__(
            parent,
            bg="#FFFFFF",
            width=width,
            height=height,
            highlightbackground="black",
            highlightthickness=1,
            padx=5,
            pady=2,
            **kwargs,
        )
        
        # Set up the test image path
        path_test_image = str(Path.joinpath(path_default, "GUIBRUSHR", "Files", "Test", "test.png"))
        
        # Store dimensions
        self.width = width
        self.height = height
        
        # Initialize image attributes
        self.image = None
        self.image1 = None
        self.image2 = None
        
        # Create and configure the canvas
        self.canvas = Canvas(self, width=self.width, height=self.height)
        self.canvas.pack()
        
        # Initialize additional data attributes
        self.string1 = None
        self.string2 = None
        
        # Display the initial test image
        self.insert_image_gui(path_test_image)
        
        # Grid the frame into the parent
        self.grid(row=row, column=column, columnspan=columnspan, rowspan=rowspan)

    def blink_preparation(
        self,
        path1: str,
        path2: str,
        path_pkl1: str,
        path_pkl2: str
    ) -> None:
        """
        Prepare images and data for blinking functionality.

        Args:
            path1: Path to the first image file
            path2: Path to the second image file
            path_pkl1: Path to the first pickle file containing additional data
            path_pkl2: Path to the second pickle file containing additional data
        """
        # Load and resize images
        self.image1 = ImageTk.PhotoImage(
            Image.open(path1).resize((int(self.width), int(self.height)))
        )
        self.image2 = ImageTk.PhotoImage(
            Image.open(path2).resize((int(self.width), int(self.height)))
        )
        
        # Load additional data from pickle files
        with open(path_pkl1, "rb") as fo:
            self.string1 = pickle.load(fo)
        with open(path_pkl2, "rb") as fo:
            self.string2 = pickle.load(fo)

    def insert_image_gui(self, path_image: str, blink: Optional[str] = None) -> None:
        """
        Display an image in the canvas.

        Args:
            path_image: Path to the image file to display
            blink: If "1" or "2", use the corresponding blink image instead of loading a new one
        """
        if blink == "1":
            image = self.image1
        elif blink == "2":
            image = self.image2
        else:
            self.image = ImageTk.PhotoImage(
                Image.open(path_image).resize((int(self.width), int(self.height)))
            )
            image = self.image
            
        self.canvas.create_image(0, 0, anchor=NW, image=image)
