#!/usr/bin/env python3
"""waybar custom module — the liturgical day in the bar.

    "custom/typikon": {
        "exec": "menologion-waybar",
        "return-type": "json",
        "interval": 1800,
        "on-click": "typikon --days 7"
    }

The class is the fast level, so the bar can colour it: style
`#custom-typikon.xerophagy` and the rest. `.obligatory` is added where a
particular law actually binds.
"""

import argparse
import collections
import html
import json
import subprocess
import sys


def run(jurisdiction, days):
    cmd = ["typikon", "--json", "--days", str(days)]
    if jurisdiction:
        cmd += ["--jurisdiction", jurisdiction]
    out = subprocess.run(cmd, capture_output=True, text=True, check=True).stdout
    parsed = json.loads(out)
    return parsed.get("days", [parsed])


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("-j", "--jurisdiction", default=None)
    ap.add_argument("-n", "--days", type=int, default=7)
    ap.add_argument("--no-emoji", action="store_true")
    ap.add_argument("--format", default="{emoji} {title}",
                    help="{emoji} {title} {feast} {fast} {fastLabel} "
                         "{season} {weekday} {churchDate}")
    args = ap.parse_args()

    try:
        days = run(args.jurisdiction, args.days)
    except FileNotFoundError:
        # Exit 0 on purpose, here and below: waybar hides a custom module whose
        # script exits non-zero, so a non-zero exit would make the module
        # vanish instead of showing why it could not answer.
        print(json.dumps({"text": "typikon?", "tooltip":
                          "typikon is not on PATH", "class": "error"}))
        return 0
    except (subprocess.CalledProcessError, ValueError) as exc:
        print(json.dumps({"text": "⚠", "tooltip": str(exc), "class": "error"}))
        return 0

    today = days[0]
    # `or ""` would blank a legitimate 0, so only None and missing become "".
    fields = {k: ("" if v is None else v) for k, v in today.items()}
    if args.no_emoji:
        fields["emoji"] = ""
    try:
        # format_map over a defaultdict: a field name that does not exist comes
        # out empty rather than raising, because the --help text advertises
        # eight names and someone will always try a ninth.
        text = args.format.format_map(collections.defaultdict(str, fields)).strip()
    except (IndexError, ValueError) as exc:
        print(json.dumps({"text": "\u26a0", "class": "error",
                          "tooltip": f"bad --format: {exc}"}))
        return 0

    tip = []
    head = today["title"]
    if today.get("churchDate") and today["churchDate"] not in head:
        head += f"   ({today['churchDate']})"
    # waybar renders the tooltip as Pango markup, so anything interpolated into
    # it has to be escaped. Nothing in the shipped data contains an ampersand,
    # but `typikon --update-menaion` fetches commemorations from a third-party
    # page, and that is exactly where one arrives.
    tip.append(f"<b>{html.escape(head)}</b>")
    if today.get("cycle"):
        tip.append(f"<i>{html.escape(today['cycle'])}</i>")
    tip.append("")
    line = today["fastLabel"]
    if today.get("obligation") == "obligatory":
        line += "  — obligatory"
    tip.append(line)
    if today.get("reason"):
        tip.append(today["reason"])
    if today.get("season"):
        tip.append(today["season"])
    for c in today.get("commemorations", []):
        if c != today["title"]:
            tip.append(f"· {c}")
    if len(days) > 1:
        tip.append("")
        for d in days[1:]:
            tip.append(f"{d['emoji']} {d['weekday'][:3]}  {d['title'][:46]}")
    tip.append("")
    tip.append(f"Pascha {today['pascha']}")

    classes = [today["fast"]]
    if today.get("obligation") == "obligatory":
        classes.append("obligatory")
    if today.get("rank"):
        classes.append(today["rank"])

    print(json.dumps({
        "text": text,
        "tooltip": "\n".join(tip),
        "class": classes,
        "alt": today["fast"],
    }, ensure_ascii=False))
    return 0


if __name__ == "__main__":
    sys.exit(main())
