#!/usr/bin/env python3
"""Build or repair a project's panes, in a fixed order.

    bin/board                     # the project in the current folder
    bin/board --folder ~/src/x    # or another one
    bin/board --replace           # close this project's panes and build again

Every page is a workspace with one pane, named after the page. The first
workspace holds a shell: it is the pane that never exits, so the session cannot
lose its first workspace to TUIOS cleanup.

Nothing here holds a workspace number. Each page asks for its workspace by name
at the moment it opens, because closing a pane deletes an emptied workspace and
renumbers the rest. Run it twice and nothing is duplicated.
"""

import os
import shlex
import sys

HERE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, os.path.join(HERE, "lib"))
import harness as h  # noqa: E402
import tuios  # noqa: E402
import project as pj  # noqa: E402

BIN = os.path.join(os.path.dirname(HERE), "bin", "harness")


def parse(argv):
    opts = {"folder": os.getcwd(), "replace": "--replace" in argv}
    for i, a in enumerate(argv):
        if a == "--folder" and i + 1 < len(argv):
            opts["folder"] = argv[i + 1]
    return opts


def pages(cfg, folder):
    """The pages, in the order they must appear on the workspace rail."""
    bin_path = BIN
    proj = cfg["paperclip"]["project"]
    task = pj.watch_task(cfg)
    # (pane name, workspace name, command). The workspace is what a person reads
    # on the rail, so it is capitalised and says what the page is for; the pane
    # keeps the program's own name. Written Workspace>pane when talking about it.
    task_pages = [
        ("shell", "Shell", "%s %s; exec zsh -i" % (
            shlex.quote(os.path.join(os.path.dirname(BIN), "shell-banner")), shlex.quote(folder))),
        ("board", "Board", "%s -screen board -project %s -folder %s" % (shlex.quote(bin_path), proj, shlex.quote(folder))),
        ("work", "Work", "%s -screen work -folder %s" % (shlex.quote(bin_path), shlex.quote(folder))),
        ("agents", "Agents", "%s -screen agents -folder %s" % (shlex.quote(bin_path), shlex.quote(folder))),
        ("reply", "Reply", "%s -screen reply -folder %s" % (shlex.quote(bin_path), shlex.quote(folder))),
        ("new", "New task", "%s -screen new -project %s" % (shlex.quote(bin_path), proj)),
        ("project", "Project", "%s -screen project -folder %s" % (shlex.quote(bin_path), shlex.quote(folder))),
        ("repair", "Repair", "%s -screen repair -folder %s" % (shlex.quote(bin_path), shlex.quote(folder))),
    ]
    # Every pane falls back to a shell, so a program that exits never leaves a
    # dead pane behind: it returns to a prompt in the project folder.
    pages = [(n, w, c if n == "shell" else c + "; exec zsh -i") for n, w, c in task_pages]
    return task, pages


def main():
    opts = parse(sys.argv[1:])
    folder = os.path.abspath(os.path.expanduser(opts["folder"]))
    cfg = pj.load(folder)
    pj.check_machine(cfg)
    session = cfg["session"]
    tuios.require_session(session)
    os.environ["PAPERCLIP_HARNESS_SESSION"] = session

    if not os.path.isfile(BIN):
        raise h.Refused(2, "no harness binary at %s; build it with 'cd tui && go build -o ../bin/harness .'" % BIN)

    task, page_list = pages(cfg, folder)
    h.say("board: %s  (session %s, folder %s)" % (cfg["paperclip"]["project"], session, folder))
    h.say("watching: %s" % task)

    if opts["replace"]:
        for name, _, _ in page_list:
            if tuios.close_pane(name, session):
                h.say("  closed %s" % name)

    for name, workspace, command in page_list:
        result, ident, ws = tuios.open_pane(
            name, workspace, folder, command, session,
            adopt_existing=(name == "shell"),
        )
        h.say("  %-9s %-8s workspace %s" % (name, result, ws))

    for number, name in tuios.arrange([(p[0], p[1]) for p in page_list], session):
        h.say("  placed %-8s workspace %s" % (name, number))

    in_use = [w for w in tuios.workspaces(session) if (w.get("window_count") or 0) > 0]
    h.say("workspaces in use: %d" % len(in_use))
    return 0


if __name__ == "__main__":
    h.main_guard(main)
