import tkinter as tk
import math

# Configuration
COMBINATION = (22, 7, 15)  # (clockwise, counter-clockwise, clockwise)

class CombinationLockApp:
    def __init__(self, root):
        self.root = root
        self.root.title("Combination Lock")

        self.canvas = tk.Canvas(root, width=300, height=350, bg="white")
        self.canvas.pack()

        # Variables
        self.angle = 0.0
        self.last_x = None
        self.entered = []
        self.turn_count = 0
        self.is_unlocked = False

        # Draw latch (simple rectangle)
        self.latch = self.canvas.create_rectangle(120, 20, 180, 60, fill="gray")
        self.canvas.tag_bind(self.latch, "<Button-1>", self.try_open_latch)

        # Combination display
        self.combo_text = self.canvas.create_text(150, 90, text=f"Combination: {COMBINATION}",
                                                  font=("Arial", 12))

        # Draw dial
        self.dial_center = (150, 200)
        self.dial = self.canvas.create_oval(50, 100, 250, 300, fill="lightgray")
        self.canvas.bind("<ButtonPress-1>", self.start_spin)
        self.canvas.bind("<B1-Motion>", self.spin_dial)

        # Draw tick marks and numbers
        self.draw_ticks()

    def draw_ticks(self):
        self.ticks = []
        r = 100
        for n in range(40):  # standard 0-39 dial
            angle = math.radians(n * 9)  # 360/40 = 9 degrees per number
            x = self.dial_center[0] + r*math.sin(angle)
            y = self.dial_center[1] - r*math.cos(angle)
            tick = self.canvas.create_text(x, y, text=str(n), font=("Arial", 8))
            self.ticks.append((tick, n))

    def start_spin(self, event):
        self.last_x = event.x

    def spin_dial(self, event):
        if self.is_unlocked:  # dial no longer spins
            return
        delta = event.x - self.last_x
        self.last_x = event.x

        # Rotate dial
        self.angle += delta * 0.8  # speed factor
        self.update_dial_display(delta)

    def update_dial_display(self, delta):
        # Move text numbers.
        # First erase old
        for tick, _ in self.ticks:
            self.canvas.delete(tick)
        # Recreate with new angle
        self.ticks.clear()
        r = 100
        for n in range(40):
            deg = n * 9 + self.angle
            x = self.dial_center[0] + r * math.sin(math.radians(deg))
            y = self.dial_center[1] - r * math.cos(math.radians(deg))
            tick = self.canvas.create_text(x, y, text=str(n), font=("Arial", 8))
            self.ticks.append((tick, n))

        # Track combination logic
        current_number = int(((-self.angle) % 360) / 9) % 40

        # Detect direction changes (left drag = clockwise, right drag = ccw)
        direction = -1 if delta > 0 else 1
        if not self.entered or self.entered[-1][1] != direction:
            self.turn_count += 1
            self.entered.append((current_number, direction))
            if self.turn_count > 3:
                self.entered = self.entered[-3:]
                self.turn_count = 3

    def try_open_latch(self, event):
        if self.is_unlocked:
            return

        # Extract only the numbers from most recent 3 turns
        numbers = [turn[0] for turn in self.entered[-3:]]
        if tuple(numbers) == COMBINATION:
            self.is_unlocked = True
            self.canvas.itemconfig(self.latch, fill="green")
            self.canvas.itemconfig(self.combo_text, text="Unlocked!")
        else:
            # Reset for another try
            self.entered.clear()
            self.turn_count = 0
            self.canvas.itemconfig(self.combo_text, text=f"Combination: {COMBINATION}")

if __name__ == "__main__":
    root = tk.Tk()
    CombinationLockApp(root)
    root.mainloop()
