import cv2
from PIL import Image, ImageTk

class ImageContainer:
    _imageData = None
    _path = None
    _history = None
    _redo_history = None

    def loadImage(self, path: str) -> None:
        """ Load image file from the path.

        :param path: Path to the image file.
        """
        imgcv2 = cv2.imread(path)
        height, width, channels = imgcv2.shape

        # Open and resize image
        self._imageData = Image.open(path)
        # PIL expects (width, height)
        self._imageData = self._imageData.resize((width, height), Image.LANCZOS)

        self._path = path
        self._history = []
        self._redo_history = []

        print("Opened image:", path)

    def getDimensions(self) -> tuple[int,int]:
        # PIL Image.size returns (width, height)
        return self._imageData.size if self._imageData is not None else (0, 0)

    def getImage(self) -> Image or None:
        return self._imageData

    def saveImage(self, path: str) -> None:
        if self._imageData is not None:
            self._imageData.save(path)

    def snapshot(self) -> None:
        """Push a copy of current image to history for undo."""
        if self._imageData is None:
            return
        # Ensure a deep copy (but PIL copy should be sufficient)
        self._history.append(self._imageData.copy())
        # New action invalidates redo history
        if self._redo_history is not None:
            self._redo_history.clear()
        # Cap history size to avoid memory blow up
        if len(self._history) > 20:
            self._history.pop(0)

    def undo(self) -> None:
        if not self._history:
            return
        # Move current state to redo stack
        if self._redo_history is None:
            self._redo_history = []
        if self._imageData is not None:
            self._redo_history.append(self._imageData.copy())
        # Restore last snapshot
        self._imageData = self._history.pop()

    def redo(self) -> None:
        if not self._redo_history:
            return
        # Moving forward: save current to undo history
        if self._imageData is not None:
            self._history.append(self._imageData.copy())
        # Apply redo state
        self._imageData = self._redo_history.pop()