"""Select the English audio track after playback starts.

── WHY KODI'S OWN SETTING IS NOT ENOUGH ─────────────────────────────────────
locale.audiolanguage and videoplayer.preferdefaultflag only work when the file
tags its audio tracks with a language. Plenty of scene releases tag them "und",
tag them wrongly, or tag nothing at all, and Kodi then falls back to track 0 -
which on a MULTI-LANG remux is frequently not English.

The add-on does not help here either: its only language filter is for Easynews,
and its player touches subtitle visibility but never the audio stream.

So this picks the track after the fact, which works regardless of how the file
is tagged: ask Kodi what streams the running file actually has, and switch if
the active one is not English.

Importable, so the agent can call it, and runnable, so it can be pointed at a
film that is already playing.

    py -3 lounge_lang.py            # fix whatever is playing now
    py -3 lounge_lang.py --dry-run
"""
from __future__ import annotations

import argparse
import sys

# Kodi reports ISO 639-2/B, but releases are inconsistent, so match generously.
ENGLISH = {"eng", "en", "english", "eng-us", "en-us", "eng-gb", "en-gb"}
# Words that appear in a track NAME when it is English even if the language
# field is empty, which is the common case for untagged releases.
ENGLISH_HINTS = ("english", "eng ", " eng", "[eng]", "(eng)")


def is_english(stream):
    language = (stream.get("language") or "").strip().lower()
    if language in ENGLISH:
        return True
    if language and language not in ("und", "unknown", ""):
        return False  # tagged as something else; believe it
    name = (stream.get("name") or "").strip().lower()
    return any(hint in name for hint in ENGLISH_HINTS)


def describe(stream):
    return "%s / %s" % (stream.get("language") or "untagged",
                        (stream.get("name") or "unnamed")[:40])


def apply(kodi, dry_run=False, log=print):
    """Switch the active player to English audio, and subtitles if it cannot."""
    players = kodi.call("Player.GetActivePlayers").get("result") or []
    if not players:
        return "nothing is playing"
    player_id = players[0]["playerid"]

    properties = kodi.call("Player.GetProperties", {
        "playerid": player_id,
        "properties": ["currentaudiostream", "audiostreams",
                       "currentsubtitle", "subtitles", "subtitleenabled"],
    }).get("result") or {}

    streams = properties.get("audiostreams") or []
    current = properties.get("currentaudiostream") or {}
    if not streams:
        return "no audio streams reported"

    log("audio tracks: %d" % len(streams))
    for stream in streams:
        marker = "->" if stream.get("index") == current.get("index") else "  "
        log("  %s [%s] %s" % (marker, stream.get("index"), describe(stream)))

    if is_english(current):
        return "already English (%s)" % describe(current)

    english = [s for s in streams if is_english(s)]
    if english:
        target = english[0]
        if dry_run:
            return "would switch to [%s] %s" % (target.get("index"), describe(target))
        kodi.call("Player.SetAudioStream",
                  {"playerid": player_id, "stream": target["index"]})
        return "switched audio to [%s] %s" % (target.get("index"), describe(target))

    # No English audio exists at all. Subtitles are the honest fallback: the
    # film is in another language and no setting can change that.
    subtitles = properties.get("subtitles") or []
    english_subs = [s for s in subtitles if is_english(s)]
    if not english_subs:
        return "no English audio and no English subtitles in this release"
    if dry_run:
        return "would enable English subtitles [%s]" % english_subs[0].get("index")
    kodi.call("Player.SetSubtitle",
              {"playerid": player_id, "subtitle": english_subs[0]["index"], "enable": True})
    return "no English audio; enabled English subtitles instead"


def main():
    parser = argparse.ArgumentParser(description=__doc__)
    parser.add_argument("--kodi-host", default="127.0.0.1")
    parser.add_argument("--kodi-port", type=int, default=9090)
    parser.add_argument("--dry-run", action="store_true")
    arguments = parser.parse_args()

    sys.path.insert(0, str(__import__("pathlib").Path(__file__).resolve().parent))
    from lounge_agent import Kodi

    kodi = Kodi(arguments.kodi_host, arguments.kodi_port)
    if not kodi.alive():
        print("Kodi is not reachable on %d" % arguments.kodi_port)
        return 1
    print(apply(kodi, dry_run=arguments.dry_run))
    return 0


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