import tkinter as tk
from dataclasses import dataclass

import ttkbootstrap as ttk
from PIL import Image, ImageTk
from ttkbootstrap.scrolled import ScrolledFrame


class Slide(tk.Frame):
    def __init__(self, preview, image: Image.Image):
        super().__init__(preview._frame)
        self.preview = preview

        self.image = image
        self.imagetk = ImageTk.PhotoImage(image)

        self.label = tk.Label(self, image=self.imagetk, borderwidth=1, relief=tk.SOLID)
        self.label.pack(fill=tk.X, pady=(0, 5))

        self.delbutton = ttk.Button(self, text="Löschen", bootstyle="danger-outline", command=self._on_delete)
        self.delbutton.pack(fill=tk.X)

        self._is_selected = False
        self.highlight = None

        self._configure_id = None
        self.bind("<Configure>", self._on_resize)
        self.label.bind("<Button-1>", self._on_select)

    def _on_resize(self, e: tk.Event):
        if self._configure_id != None:
            self.after_cancel(self._configure_id)
        self._configure_id = self.after(100, self._on_final_resize)

    def _on_select(self, e: tk.Event):
        if self._is_selected:
            self._on_unselect()
        else:
            self._is_selected = True
            self.highlight = tk.Label(self, text="Ausgewählt", bg="green")
            self.highlight.place(x=0, y=0)
            self.preview.notify_selection(self)

    def _on_unselect(self):
        self._is_selected = False
        if self.highlight is not None:
            self.highlight.destroy()

    def _on_final_resize(self):
        thumbnail = self.image.copy()
        thumbnail.thumbnail(size=(self.winfo_width(), self.image.height), resample=Image.NEAREST)
        self.imagetk = ImageTk.PhotoImage(thumbnail)

        self.label.configure(image=self.imagetk)
        self._configure_id = None

    def _on_delete(self):
        self.preview.remove(self)


class SlidePreview(ScrolledFrame):
    def __init__(self, parent, *args, columns: int = 4, **kwargs):
        super().__init__(parent, *args, **kwargs)

        self._frame = tk.Frame(self)
        self._frame.pack(fill=tk.BOTH, expand=True)

        self.columns = columns
        for column in range(columns):
            self._frame.grid_columnconfigure(column, weight=1)

        self._selected_index = -1
        self._slides = []

    def _on_resize(self, e: tk.Event):
        slide = self._slides[0]
        slide.grid_forget()
        slide.grid(row=0, column=0, sticky=tk.EW)

    def notify_selection(self, selected: Slide):
        self._selected_index = self._slides.index(selected)
        for slide in self._slides:
            if slide is not selected:
                slide._on_unselect()

    def notify_unselected(self, unselected: Slide):
        if self._slides.index(unselected) == self._selected_index:
            self._selected_index = -1

    def add(self, slide: Image.Image):
        index = len(self._slides)

        s = Slide(self, slide)
        s.grid(row=index // self.columns, column=index % self.columns, sticky=tk.NSEW, padx=10, pady=10)

        self._slides.append(s)

    def insert(self, slide: Image.Image, index: int):
        s = Slide(self, slide)
        self._slides.insert(index, s)

        for index, slide in enumerate(self._slides):
            slide.grid_forget()
            slide.grid(row=index // self.columns, column=index % self.columns, sticky=tk.NSEW, padx=10, pady=10)
            slide._on_final_resize()

        if index <= self._selected_index:
            self._selected_index += 1

    def remove(self, slide: Slide):
        index = self._slides.index(slide)
        if index < 0:
            return

        if index == self._selected_index:
            self._selected_index = -1
        elif index < self._selected_index:
            self._selected_index -= 1

        slide.destroy()
        del self._slides[index]

        for index, slide in enumerate(self._slides[index:], start=index):
            slide.grid_forget()
            slide.grid(row=index // self.columns, column=index % self.columns, sticky=tk.NSEW, padx=10, pady=10)

    def clear(self):
        for slide in self._slides:
            slide.destroy()
        self._slides = []
        self._selected_index = -1

    def __len__(self):
        return len(self._slides)

    def get_images(self) -> list[Image.Image]:
        return [slide.image for slide in self._slides]


if __name__ == "__main__":
    main = tk.Tk()
    main.geometry("800x400")

    sp = SlidePreview(main)
    sp.pack(fill=tk.BOTH, expand=True)

    for filename in [f"{i:02}" for i in range(16)]:
        img = Image.open(f"machine learning in der radiologie_5ebbrbz/{filename}.png")
        sp.add(img)

    main.mainloop()
