import os
import glob
import random
from tkinter import Tk, Button, filedialog, Label, Checkbutton, IntVar

from PIL import Image

# Supported image extensions
IMAGE_EXTENSIONS = ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.webp']

class ImageIndexerApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Image Indexer")
        
        self.open_button = Button(self.root, text="Open Folder", command=self.on_open_folder)
        self.open_button.pack()
        
        self.next_button = Button(self.root, text="Next Image", command=self.next_image, state='disabled')
        self.next_button.pack()

        self.prev_button = Button(self.root, text="Previous Image", command=self.prev_image, state='disabled')
        self.prev_button.pack()
        
        self.random_button = Button(self.root, text="Random Image", command=self.random_image, state='disabled')
        self.random_button.pack()

        self.total_images_label = Label(self.root, text="Total images: 0")
        self.total_images_label.pack()

        # Label to show the count of images displayed
        self.img_count_label = Label(self.root, text="Images shown: 0")
        self.img_count_label.pack()

        self.random_mode = IntVar()
        self.random_checkbox = Checkbutton(self.root, text="Random", variable=self.random_mode)
        self.random_checkbox.pack()

        self.limit_mode = IntVar()
        self.limit_checkbox = Checkbutton(self.root, text="Limit to 20", variable=self.limit_mode)
        self.limit_checkbox.pack()

        self.img_num = 0
        self.image_files = []
        self.image_history = []
        self.random_pool = []  # Store images not yet shown in random mode
        self.img_count = 0  # Counter for images shown
        self.img_limit = 20  # Restrict to 20 images

    def is_image(self, filename):
        """Check if a file is an image that can be opened."""
        try:
            Image.open(filename)
            return True
        except (IOError, FileNotFoundError):
            return False

    def on_open_folder(self):
        """Open a directory and list all valid image files."""
        directory = filedialog.askdirectory()
        if not directory:
            return
        self.image_files = self.list_images(directory)
        self.img_num = 0
        self.image_history = []
        self.random_pool = self.image_files.copy()
        self.img_count = 0
        self.total_images_label.config(text=f"Total images: {len(self.image_files)}")
        self.update_img_count_label()
        if self.image_files:
            # Enable buttons after directory is loaded
            self.next_button.config(state='normal')
            self.prev_button.config(state='normal')
            self.random_button.config(state='normal')

    def next_image(self):
        """Display the next image in a linear or random fashion without repetition."""
        if not self.image_files or (self.limit_mode.get() and self.img_count >= self.img_limit):
            return

        if not self.random_mode.get():
            # Linear mode
            self.img_num = (self.img_num + 1) % len(self.image_files)
        else:
            # Random mode without repetition
            if not self.random_pool:
                self.shuffle_images()
            self.img_num = self.random_pool.pop(0)  # Get the next image index from the shuffled pool

        self.display_image(add_to_history=True)
        self.img_count += 1
        self.update_img_count_label()

    def prev_image(self):
        """Display the previous image from the history, or in a linear/random fashion if empty."""
        if self.image_history:
            # Use history to go back
            self.img_num = self.image_history.pop()
        else:
            if self.random_mode.get():
                # Random mode without repetition
                if not self.random_pool:
                    self.shuffle_images()
                self.img_num = self.random_pool.pop(0)
            else:
                # Linear mode
                self.img_num = (self.img_num - 1) % len(self.image_files)

        self.display_image(add_to_history=False)

    def shuffle_images(self):
        """Shuffle the image files for random mode."""
        self.random_pool = list(range(len(self.image_files)))
        random.shuffle(self.random_pool)  # Shuffle the indexes

    def random_image(self):
        """Selects a random image from the pool and displays it."""
        if self.image_files:
            if not self.random_pool:
                self.random_pool = self.image_files.copy()
            self.img_num = random.choice(self.random_pool)
            self.random_pool.remove(self.img_num)
            self.display_image(add_to_history=True)

    def display_image(self, add_to_history):
        """Display the current image and update the history if required."""
        # Fixed the TypeError: now using the index to access the image file
        current_file = self.image_files[self.img_num]
        print(f"{self.img_num + 1}: {current_file}")
        
        if add_to_history:
            # Add the current index to the history, not the file itself
            self.image_history.append(self.img_num)
        
        # Potential code to actually show the image if desired - Replace the print statement
        # image = Image.open(current_file)
        # image.show()

        self.prev_button.config(state='normal')  # Always enable 'Previous' button

    def update_img_count_label(self):
        """Update the label that shows the count of images displayed."""
        self.img_count_label.config(text=f"Images shown: {self.img_count}")

    def list_images(self, directory):
        """List all the image files in a given directory."""
        images = []
        for extension in IMAGE_EXTENSIONS:
            images.extend(glob.glob(os.path.join(directory, f"*{extension}")))
        images = [img for img in images if self.is_image(img)]
        return images

if __name__ == '__main__':
    root = Tk()
    app = ImageIndexerApp(root)
    root.mainloop()

it returns the following error:
line 128, in display_image
    current_file = self.image_files[self.img_num]
                   ~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^
TypeError: list indices must be integers or slices, not str