import tkinter as tk

# --- Constants ---
# You can adjust these to change the abacus's appearance
NUM_RODS = 13
BEAD_COLOR = "#B22222"  # Firebrick
ROD_COLOR = "#8B4513"   # SaddleBrown
FRAME_COLOR = "#8B4513"
BAR_COLOR = "#A0522D"   # Sienna
BG_COLOR = "#F5DEB3"    # Wheat
BEAD_WIDTH = 50
BEAD_HEIGHT = 25
ROD_SPACING = 60
FRAME_THICKNESS = 20
BAR_THICKNESS = 10

# --- Main Application Class ---
class AbacusApp:
    """
    An interactive abacus application built with tkinter.
    """
    def __init__(self, root):
        """Initializes the abacus application."""
        self.root = root
        self.root.title("Interactive Abacus")
        self.root.resizable(False, False)

        # Calculate canvas dimensions based on abacus size
        self.canvas_width = (NUM_RODS + 1) * ROD_SPACING
        self.canvas_height = 8 * BEAD_HEIGHT + 2 * FRAME_THICKNESS
        
        # --- Data Structure ---
        # Stores the state of the abacus.
        # For each rod, we store a list: [heaven_bead_active, num_earth_beads_active]
        # heaven_bead_active: 1 if down (active), 0 if up (inactive)
        # num_earth_beads_active: 0-4, number of earth beads pushed up (active)
        self.bead_states = [[0, 0] for _ in range(NUM_RODS)]

        # --- UI Elements ---
        self.canvas = tk.Canvas(
            root,
            width=self.canvas_width,
            height=self.canvas_height,
            bg=BG_COLOR
        )
        self.canvas.pack(pady=10)

        self.value_label = tk.Label(
            root,
            text="0",
            font=("Arial", 24, "bold"),
            pady=10
        )
        self.value_label.pack()

        # --- Event Binding ---
        self.canvas.bind("<Button-1>", self.on_canvas_click)

        # --- Initial Draw ---
        self.draw_abacus()
        self.update_value()

    def draw_abacus(self):
        """Clears and redraws the entire abacus based on the current state."""
        self.canvas.delete("all")
        self.draw_frame()
        
        for i in range(NUM_RODS):
            self.draw_rod(i)

    def draw_frame(self):
        """Draws the outer frame and the central reckoning bar."""
        # Outer frame
        self.canvas.create_rectangle(
            FRAME_THICKNESS / 2, FRAME_THICKNESS / 2,
            self.canvas_width - FRAME_THICKNESS / 2,
            self.canvas_height - FRAME_THICKNESS / 2,
            width=FRAME_THICKNESS,
            outline=FRAME_COLOR
        )
        # Reckoning bar (the horizontal bar in the middle)
        self.bar_y = self.canvas_height / 2 - 2.5 * BEAD_HEIGHT
        self.canvas.create_rectangle(
            FRAME_THICKNESS, self.bar_y - BAR_THICKNESS / 2,
            self.canvas_width - FRAME_THICKNESS, self.bar_y + BAR_THICKNESS / 2,
            fill=BAR_COLOR,
            width=0
        )

    def draw_rod(self, rod_index):
        """Draws a single rod and its beads based on its state."""
        rod_x = (rod_index + 1) * ROD_SPACING
        
        # Draw the rod itself
        self.canvas.create_line(
            rod_x, FRAME_THICKNESS,
            rod_x, self.canvas_height - FRAME_THICKNESS,
            fill=ROD_COLOR,
            width=2
        )

        # --- Draw Heaven Bead (value of 5) ---
        heaven_state = self.bead_states[rod_index][0]
        if heaven_state == 0: # Inactive (up)
             y_center = self.bar_y - 1.5 * BEAD_HEIGHT
        else: # Active (down)
             y_center = self.bar_y - 0.5 * BEAD_HEIGHT
        self.draw_bead(rod_x, y_center)

        # --- Draw Earth Beads (value of 1 each) ---
        earth_beads_up = self.bead_states[rod_index][1]
        
        # Draw active beads (up)
        for i in range(earth_beads_up):
            y_center = self.bar_y + (i + 0.5) * BEAD_HEIGHT
            self.draw_bead(rod_x, y_center)
            
        # Draw inactive beads (down)
        for i in range(4 - earth_beads_up):
            y_center = self.bar_y + (earth_beads_up + i + 1.5) * BEAD_HEIGHT
            self.draw_bead(rod_x, y_center)

    def draw_bead(self, x, y):
        """Helper function to draw a single bead centered at (x, y)."""
        self.canvas.create_oval(
            x - BEAD_WIDTH / 2, y - BEAD_HEIGHT / 2,
            x + BEAD_WIDTH / 2, y + BEAD_HEIGHT / 2,
            fill=BEAD_COLOR,
            width=2,
            outline="black"
        )

    def on_canvas_click(self, event):
        """Handles mouse clicks on the canvas to move beads."""
        # Determine which rod was clicked
        rod_index = int((event.x - ROD_SPACING / 2) / ROD_SPACING)
        if not (0 <= rod_index < NUM_RODS):
            return # Click was outside the rods

        # Check if the click was on the heaven bead (above the bar)
        if event.y < self.bar_y:
            # Toggle heaven bead state
            self.bead_states[rod_index][0] = 1 - self.bead_states[rod_index][0]
        # Check if the click was on the earth beads (below the bar)
        else:
            # Determine which bead was clicked based on y-position
            bead_pos = int((event.y - self.bar_y) / BEAD_HEIGHT)
            
            # Find the state of the clicked bead
            num_up = self.bead_states[rod_index][1]
            
            if bead_pos <= num_up: # Clicked on an 'up' bead
                # Move this bead and all above it down
                self.bead_states[rod_index][1] = bead_pos - 1
            else: # Clicked on a 'down' bead
                # Move this bead and all below it up
                self.bead_states[rod_index][1] = bead_pos
        
        # Redraw and update the display
        self.draw_abacus()
        self.update_value()

    def update_value(self):
        """Calculates and displays the number represented by the abacus."""
        total_value = 0
        for i in range(NUM_RODS):
            heaven_val = self.bead_states[i][0] * 5
            earth_val = self.bead_states[i][1]
            rod_value = heaven_val + earth_val
            
            # Calculate place value (units, tens, hundreds, etc. from right to left)
            place_value = 10**(NUM_RODS - 1 - i)
            total_value += rod_value * place_value
            
        self.value_label.config(text=f"{total_value:,}")


# --- Main Execution ---
if __name__ == "__main__":
    main_window = tk.Tk()
    app = AbacusApp(main_window)
    main_window.mainloop()
