import curses
import os
from pathlib import Path
from fontTools.ttLib import TTFont
 
KITTY_CONF = Path.home() / ".config/kitty/kitty.conf"
BACKUP_CONF = Path.home() / ".config/kitty/kitty-old.conf"
 
 
def get_installed_fonts():
    font_dirs = [
        os.path.expanduser("~/.local/share/fonts"),
        "/usr/share/fonts",
        "/usr/local/share/fonts",
    ]
    font_files = []
    for font_dir in font_dirs:
        if os.path.isdir(font_dir):
            for root, _, files in os.walk(font_dir):
                for f in files:
                    if f.lower().endswith((".ttf", ".otf")):
                        font_files.append(os.path.join(root, f))
 
    families = set()
    for font_file in font_files:
        try:
            font = TTFont(font_file)
            name = font["name"]
            for record in name.names:
                if record.nameID == 1:
                    fam = record.toUnicode()
                    if fam:
                        families.add(fam)
                    break
            font.close()
        except Exception:
            pass
    return sorted(families)
 
 
FONT_FAMILIES = get_installed_fonts()
if not FONT_FAMILIES:
    FONT_FAMILIES = ["monospace"]
 
 
def load_external_config(path):
    path = Path(path).expanduser()
    if not path.exists():
        return None
 
    opacity = 9
    blur = 0
    hide_decor = False
    font_size = 12
    font_family = FONT_FAMILIES[0]
 
    with path.open(encoding="utf-8") as f:
        for line in f:
            line = line.strip()
            if line.startswith("background_opacity"):
                try:
                    opacity = int(float(line.split()[1]) * 10)
                except:
                    pass
            elif line.startswith("background_blur"):
                try:
                    blur = int(line.split()[1])
                except:
                    pass
            elif line.startswith("hide_window_decorations"):
                hide_decor = (line.split()[1].lower() == "yes")
            elif line.startswith("font_size"):
                try:
                    font_size = int(line.split()[1])
                except:
                    pass
            elif line.startswith("font_family"):
                fam = line.split(maxsplit=1)[1].strip()
                if fam in FONT_FAMILIES:
                    font_family = fam
 
    return opacity, blur, hide_decor, font_size, font_family
 
 
def load_kitty_conf():
    return load_external_config(KITTY_CONF)
 
 
def write_new_kitty_conf(opacity, blur, hide_decor, font_size, font_family):
    if KITTY_CONF.exists():
        if BACKUP_CONF.exists():
            BACKUP_CONF.unlink()
        KITTY_CONF.rename(BACKUP_CONF)
 
    lines = [
        f"background_opacity {opacity:.1f}",
        f"background_blur {blur}",
        f"hide_window_decorations {'yes' if hide_decor else 'no'}",
        f"font_size {font_size}",
        f"font_family {font_family}",
    ]
 
    KITTY_CONF.write_text("\n".join(lines) + "\n")
 
 
def draw_slider(stdscr, label, value, max_value, y, x, selected):
    stdscr.addstr(y, x, label)
    bar_length = 20
    slider = "["
    scaled_value = int((value / max_value) * bar_length)
    for i in range(bar_length):
        if i < scaled_value:
            slider += "="
        elif i == scaled_value:
            slider += "|"
        else:
            slider += " "
    slider += f"] {value}/{max_value}"
    if selected:
        stdscr.addstr(y, x + len(label) + 1, slider, curses.A_REVERSE)
    else:
        stdscr.addstr(y, x + len(label) + 1, slider)
 
 
def draw_toggle(stdscr, label, value, y, x, selected):
    val_str = "yes" if value else "no"
    text = f"{label}: {val_str}"
    if selected:
        stdscr.addstr(y, x, text, curses.A_REVERSE)
    else:
        stdscr.addstr(y, x, text)
 
 
def draw_select(stdscr, label, options, current_index, y, x, selected):
    text = f"{label}: {options[current_index]}"
    if selected:
        stdscr.addstr(y, x, text, curses.A_REVERSE)
    else:
        stdscr.addstr(y, x, text)
 
 
def main(stdscr):
    curses.curs_set(0)
    stdscr.keypad(True)
    height, width = stdscr.getmaxyx()
 
    opacity_value, blur_value, hide_window_decor, font_size, font_family = load_kitty_conf()
    font_size = max(8, min(font_size, 40))
    try:
        font_family_index = FONT_FAMILIES.index(font_family)
    except ValueError:
        font_family_index = 0
 
    selected_control = 0
    import_path = ""
    editing_import = False
 
    total_controls = 6  # 5 settings + 1 import input
 
    while True:
        stdscr.clear()
        stdscr.addstr(1, (width - len("Kitty Config TUI")) // 2, "Kitty Config TUI", curses.A_BOLD)
        stdscr.addstr(3, 4, "Appearance", curses.A_UNDERLINE)
 
        draw_slider(stdscr, "Opacity        ", opacity_value, 10, y=5, x=4, selected=(selected_control == 0 and not editing_import))
        draw_slider(stdscr, "Background Blur", blur_value, 10, y=7, x=4, selected=(selected_control == 1 and not editing_import))
        draw_toggle(stdscr, "Hide Decorations", hide_window_decor, y=9, x=4, selected=(selected_control == 2 and not editing_import))
        draw_slider(stdscr, "Font Size      ", font_size, 40, y=11, x=4, selected=(selected_control == 3 and not editing_import))
        draw_select(stdscr, "Font Family    ", FONT_FAMILIES, font_family_index, y=13, x=4, selected=(selected_control == 4 and not editing_import))
 
        # Import config line with editable input
        import_label = "Import Config  : "
        if selected_control == 5:
            stdscr.addstr(15, 4, import_label, curses.A_REVERSE)
            if editing_import:
                curses.curs_set(1)
                stdscr.addstr(15, 4 + len(import_label), import_path, curses.A_REVERSE)
                stdscr.move(15, 4 + len(import_label) + len(import_path))
            else:
                curses.curs_set(0)
                stdscr.addstr(15, 4 + len(import_label), import_path)
        else:
            curses.curs_set(0)
            stdscr.addstr(15, 4, import_label + import_path)
 
        stdscr.refresh()
 
        ch = stdscr.getch()
        if editing_import:
            if ch in (curses.KEY_ENTER, 10, 13):
                # Try to load config file from import_path
                result = load_external_config(import_path)
                if result:
                    opacity_value, blur_value, hide_window_decor, font_size, font_family = result
                    font_family_index = FONT_FAMILIES.index(font_family) if font_family in FONT_FAMILIES else 0
                editing_import = False
                import_path = ""
                curses.curs_set(0)
            elif ch in (27, ord(' ')):  # ESC or space to cancel editing
                editing_import = False
                import_path = ""
                curses.curs_set(0)
            elif ch in (curses.KEY_BACKSPACE, 127, 8):
                import_path = import_path[:-1]
            else:
                try:
                    import_path += chr(ch)
                except:
                    pass
        else:
            if ch == curses.KEY_UP:
                selected_control = (selected_control - 1) % total_controls
            elif ch == curses.KEY_DOWN:
                selected_control = (selected_control + 1) % total_controls
            elif ch == curses.KEY_LEFT:
                if selected_control == 0 and opacity_value > 0:
                    opacity_value -= 1
                elif selected_control == 1 and blur_value > 0:
                    blur_value -= 1
                elif selected_control == 3 and font_size > 8:
                    font_size -= 1
                elif selected_control == 4:
                    font_family_index = (font_family_index - 1) % len(FONT_FAMILIES)
            elif ch == curses.KEY_RIGHT:
                if selected_control == 0 and opacity_value < 10:
                    opacity_value += 1
                elif selected_control == 1 and blur_value < 10:
                    blur_value += 1
                elif selected_control == 3 and font_size < 40:
                    font_size += 1
                elif selected_control == 4:
                    font_family_index = (font_family_index + 1) % len(FONT_FAMILIES)
            elif ch == ord(' '):
                if selected_control == 2:
                    hide_window_decor = not hide_window_decor
            elif ch == ord('\n') or ch == curses.KEY_ENTER:
                if selected_control == 5:
                    editing_import = True
            elif ch == ord('q'):
                break
            elif ch == ord('w'):
                write_new_kitty_conf(opacity_value / 10, blur_value, hide_window_decor, font_size, FONT_FAMILIES[font_family_index])
            elif ch == ord('W'):
                write_new_kitty_conf(opacity_value / 10, blur_value, hide_window_decor, font_size, FONT_FAMILIES[font_family_index])
                break
 
 
if __name__ == "__main__":
    curses.wrapper(main)