import tkinter as tk
from tkinter import ttk

class RoadSelectionDialog:
    def __init__(self, master, get_roads, on_apply):
        self.master = master
        self.on_apply = on_apply
        self.window = tk.Toplevel(master)
        self.window.title("Select Roads")
        self.window.geometry("320x420")
        self.window.resizable(False, True)

        frame = ttk.Frame(self.window, padding="10")
        frame.grid(row=0, column=0, sticky=(tk.N, tk.S, tk.W, tk.E))

        ttk.Label(frame, text="Select roads to spawn:", font=("Arial", 10, "bold")).grid(row=0, column=0, sticky=tk.W, pady=(0,8))

        self.selected_vars = []
        roads = list(get_roads())
        canvas = tk.Canvas(frame, borderwidth=0, highlightthickness=0)
        scroll_y = ttk.Scrollbar(frame, orient="vertical", command=canvas.yview)
        list_frame = ttk.Frame(canvas)
        list_frame.bind("<Configure>", lambda _e: canvas.configure(scrollregion=canvas.bbox("all")))
        canvas.create_window((0,0), window=list_frame, anchor="nw")
        canvas.configure(yscrollcommand=scroll_y.set, height=280)

        for idx, name in enumerate(roads):
            var = tk.BooleanVar(value=False)
            cb = ttk.Checkbutton(list_frame, text=name, variable=var)
            cb.grid(row=idx, column=0, sticky=tk.W)
            self.selected_vars.append((name, var))

        canvas.grid(row=1, column=0, sticky=(tk.W, tk.E, tk.N, tk.S))
        scroll_y.grid(row=1, column=1, sticky=(tk.N, tk.S))

        btn_frame = ttk.Frame(frame)
        btn_frame.grid(row=2, column=0, pady=(10,0), sticky=(tk.W, tk.E))
        ttk.Button(btn_frame, text="OK", command=self.apply_and_close).grid(row=0, column=0, padx=(0,6))
        ttk.Button(btn_frame, text="Cancel", command=self.window.withdraw).grid(row=0, column=1)

        self.window.lift(); self.window.focus_force()

    def apply_and_close(self):
        try:
            names = [name for name, var in self.selected_vars if var.get()]
            self.on_apply(names)
        finally:
            self.window.withdraw()

