import os
import tkinter as tk
from tkinterdnd2 import DND_FILES, TkinterDnD
from tkinter import filedialog, messagebox
from PIL import Image

class SkyboxRotatorApp(TkinterDnD.Tk):
    def __init__(self):
        super().__init__()

        self.title("Skybox Rotator")
        self.geometry("500x200")
        
        # Dictionary to hold images keyed by suffix: {suffix: (PIL_Image, folder, prefix)}
        self.suffix_map = {}

        # Create a frame to hold the drag-and-drop label and buttons
        frame = tk.Frame(self)
        frame.pack(expand=True, fill=tk.BOTH, padx=10, pady=10)

        # Create label to display instructions
        self.drop_label = tk.Label(
            frame, 
            text="Drag and drop exactly 6 TGA files ending in up, dn, ft, bk, lf, rt",
            relief=tk.RIDGE, 
            width=60, 
            height=4
        )
        self.drop_label.pack(pady=5, fill=tk.X)
        
        # Enable drop functionality on the label
        self.drop_label.drop_target_register(DND_FILES)
        self.drop_label.dnd_bind('<<Drop>>', self.drop_event)

        # Buttons for rotations
        btn_frame = tk.Frame(frame)
        btn_frame.pack(pady=5)

        turn_90_btn = tk.Button(btn_frame, text="Turn 90", command=self.turn_90_clicked)
        turn_90_btn.pack(side=tk.LEFT, padx=5)

        turn_180_btn = tk.Button(btn_frame, text="Turn 180", command=self.turn_180_clicked)
        turn_180_btn.pack(side=tk.LEFT, padx=5)

        turn_270_btn = tk.Button(btn_frame, text="Turn 270", command=self.turn_270_clicked)
        turn_270_btn.pack(side=tk.LEFT, padx=5)

    def drop_event(self, event):
        raw_data = event.data.strip()
        # For example, using the splitlist fallback approach:
        paths = self.tk.splitlist(raw_data)
        if len(paths) == 1 and ' ' in paths[0]:
            paths = paths[0].split()

        self.suffix_map.clear()

        valid_suffixes = {"up", "dn", "ft", "bk", "lf", "rt"}
        for p in paths:
            p = p.strip().replace('"','')
            if os.path.splitext(p)[1].lower() != ".tga":
                continue

            filename = os.path.basename(p)
            folder = os.path.dirname(p)
            base, _ = os.path.splitext(filename)
            suffix = base[-2:].lower()
            if suffix not in valid_suffixes:
                continue

            prefix = base[:-2]
            try:
                # Force full load and conversion
                with Image.open(p) as temp_img:
                    # TGA can be RGBA, or partially loaded, etc.
                    # Convert to 24-bit in memory
                    img = temp_img.convert("RGB").copy()
                self.suffix_map[suffix] = (img, folder, prefix)
            except Exception as e:
                print(f"Error loading {p}: {e}")

        # Verify we have all 6
        if len(self.suffix_map) == 6 and all(s in self.suffix_map for s in valid_suffixes):
            messagebox.showinfo("Success", "Successfully loaded 6 TGA files!")
        else:
            messagebox.showwarning("Warning", 
                "Did not detect a complete set of 6 TGA files (up, dn, ft, bk, lf, rt)."
            )


    def turn_90_clicked(self):
        """Perform a single 90° turn operation, then save."""
        if not self.check_six_images_loaded():
            return
        self.turn_90()
        self.save_images()
        messagebox.showinfo("Done", "Turn 90 completed and images saved.")

    def turn_180_clicked(self):
        """Perform 90° turn operation twice, then save."""
        if not self.check_six_images_loaded():
            return
        self.turn_90()
        self.turn_90()
        self.save_images()
        messagebox.showinfo("Done", "Turn 180 completed and images saved.")

    def turn_270_clicked(self):
        """Perform 90° turn operation thrice, then save."""
        if not self.check_six_images_loaded():
            return
        self.turn_90()
        self.turn_90()
        self.turn_90()
        self.save_images()
        messagebox.showinfo("Done", "Turn 270 completed and images saved.")

    def turn_90(self):
        """
        Rotate:
            up -> rotate 90° CW (PIL rotate(-90))
            dn -> rotate 90° CCW (PIL rotate(90))

        Rename suffixes (all at once):
            ft -> rt
            lf -> ft
            bk -> lf
            rt -> bk

        up/dn keep their suffix but are physically rotated.
        """
        new_map = {}
        
        # 1) Rotate up/dn physically
        if 'up' in self.suffix_map:
            img, folder, prefix = self.suffix_map['up']
            img = img.rotate(-90, expand=True)  # 90° clockwise
            new_map['up'] = (img, folder, prefix)

        if 'dn' in self.suffix_map:
            img, folder, prefix = self.suffix_map['dn']
            img = img.rotate(90, expand=True)   # 90° counter-clockwise
            new_map['dn'] = (img, folder, prefix)

        # 2) Rename ft->rt, lf->ft, bk->lf, rt->bk
        # For each of these, no physical rotation—just rename.
        rename_map = {
            'ft': 'rt',
            'lf': 'ft',
            'bk': 'lf',
            'rt': 'bk'
        }
        
        for old_suffix, new_suffix in rename_map.items():
            if old_suffix in self.suffix_map:
                img, folder, prefix = self.suffix_map[old_suffix]
                new_map[new_suffix] = (img, folder, prefix)
        
        # Update suffix_map
        self.suffix_map = new_map

    def save_images(self):
        """
        Save all images in self.suffix_map back to original folder (prefix + suffix + .tga)
        as 24-bit compressed TGA.
        """
        for suffix, (img, folder, prefix) in self.suffix_map.items():
            # Ensure it's 24-bit (RGB)
            if img.mode != 'RGB':
                img = img.convert('RGB')

            new_filename = prefix + suffix + ".tga"
            out_path = os.path.join(folder, new_filename)
            
            # Save with RLE compression for TGA
            img.save(out_path, format="TGA", compression="tga_rle")

            # Store updated PIL image (in case we do multiple transformations)
            self.suffix_map[suffix] = (img, folder, prefix)

    def check_six_images_loaded(self):
        """Ensure we have exactly 6 images in the map."""
        if len(self.suffix_map) != 6:
            messagebox.showerror("Error", "You must drop 6 valid images first.")
            return False
        return True

    @staticmethod
    def split_tkdnd_filename_list(data):
        """
        Splits the raw string from TkinterDnD's drop event into a list of file paths.
        Usually, this might look like: {path1} {path2} or just a single {path}.
        """
        # Remove surrounding braces and split by ' } {'
        # E.g.: "{C:/some path/file1.tga} {C:/some path/file2.tga}"
        # This approach is a bit naive but works for typical paths (no nested braces).
        items = []
        # We can split on curly braces carefully
        # 1) Trim any leading/trailing whitespace
        data = data.strip()
        # 2) A simple approach: each file is in {braces}, so split by '}' then strip '{'
        # but watch out for empty pieces.
        chunks = data.split('}')
        for c in chunks:
            c = c.replace('{', '').replace('}', '').strip()
            if c:
                items.append(c)
        return items


if __name__ == "__main__":
    app = SkyboxRotatorApp()
    app.mainloop()
