#!/usr/bin/env python3
import os
import sys
import re
from typing import Optional, Tuple

CTRL_PATTERN = re.compile(r'CTRL \+\s*(\S+)')  # captures the token after "CTRL +"

def find_first_ctrl(lines):
    """
    Return (line_index, match) for the first occurrence of 'CTRL +' anywhere in the file,
    or (None, None) if not found.
    """
    for i, line in enumerate(lines):
        m = CTRL_PATTERN.search(line)
        if m:
            return i, m
    return None, None

def replace_at_match(line: str, match: re.Match, letter: str) -> str:
    """Replace exactly the matched 'CTRL + <token>' with 'CTRL + <letter>'."""
    start, end = match.span()
    return line[:start] + f"CTRL + {letter}" + line[end:]

def ensure_line_ctrl_letter(lines, idx: int, letter: str) -> Tuple[bool, Optional[str], Optional[str]]:
    """
    Ensure that line idx has a 'CTRL +' occurrence set to the given letter.
    Returns (changed, before, after). If no 'CTRL +' on that line, returns (False, None, None).
    """
    if idx < 0 or idx >= len(lines):
        return False, None, None
    m = CTRL_PATTERN.search(lines[idx])
    if not m:
        return False, None, None
    before = lines[idx].rstrip("\n")
    new_line = replace_at_match(lines[idx], m, letter)
    changed = (new_line != lines[idx])
    if changed:
        lines[idx] = new_line
    after = lines[idx].rstrip("\n")
    return changed, before, after

def process_file(filepath: str, with_ctrl_l: bool, apply_changes: bool=False) -> None:
    with open(filepath, "r", encoding="utf-8") as f:
        lines = f.readlines()

    first_idx, first_match = find_first_ctrl(lines)
    if first_match is None:
        print(f"[skip] No 'CTRL +' found in {filepath}")
        return

    # Is the first occurrence already CTRL + F (allowing extra spaces after '+')?
    token_after = first_match.group(1)  # what currently follows "CTRL +"
    if token_after.strip().upper() == "F":
        print(f"[skip] {filepath} (first 'CTRL +' is already 'CTRL + F')")
        return

    print(f"[plan] {filepath}")
    # Record planned changes (for dry-run display)
    planned = []

    # 1) First occurrence line -> CTRL + F
    changed_1, before_1, after_1 = ensure_line_ctrl_letter(lines, first_idx, "F")
    if changed_1:
        planned.append((first_idx, before_1, after_1))
    else:
        print(f"  [warn] Expected 'CTRL +' on line {first_idx+1} but couldn't modify it.")

    # 2) Next line -> CTRL + H
    changed_2, before_2, after_2 = ensure_line_ctrl_letter(lines, first_idx + 1, "H")
    if changed_2:
        planned.append((first_idx + 1, before_2, after_2))
    else:
        print(f"  [warn] Expected a 'CTRL +' on the next line ({first_idx+2}), but none found.")

    # 3) Only for hints2_xy: line after next -> CTRL + L
    if with_ctrl_l:
        changed_3, before_3, after_3 = ensure_line_ctrl_letter(lines, first_idx + 2, "L")
        if changed_3:
            planned.append((first_idx + 2, before_3, after_3))
        else:
            print(f"  [warn] Expected a 'CTRL +' on the line after next ({first_idx+3}), but none found.")

    # Show before/after (both dry-run and apply)
    for idx, before, after in planned:
        print(f"  line {idx+1}:")
        print(f"    - {before}")
        print(f"    + {after}")

    if not planned:
        print(f"[skip] {filepath} (nothing to change)")
        return

    if apply_changes:
        with open(filepath, "w", encoding="utf-8") as f:
            f.writelines(lines)
        print(f"[apply] Wrote changes to {filepath}")
    else:
        print(f"[dry-run] No changes written to {filepath}")

def main():
    apply_changes = "--apply" in sys.argv
    root = os.getcwd()
    total_seen = total_changed = 0

    for entry in os.listdir(root):
        folder_path = os.path.join(root, entry)
        if not os.path.isdir(folder_path):
            continue

        lang = entry
        hints2 = os.path.join(folder_path, f"hints2_{lang}")
        hints2_pre = os.path.join(folder_path, f"hints2_pre_gtk3_20_{lang}")

        if os.path.isfile(hints2):
            total_seen += 1
            process_file(hints2, with_ctrl_l=True, apply_changes=apply_changes)
            total_changed += 1
        if os.path.isfile(hints2_pre):
            total_seen += 1
            process_file(hints2_pre, with_ctrl_l=False, apply_changes=apply_changes)
            total_changed += 1

    mode = "APPLY" if apply_changes else "DRY-RUN"
    print(f"\nDone. Mode: {mode}. Files inspected: {total_seen}.")

if __name__ == "__main__":
    main()

