#!/usr/bin/env python3
import gi
gi.require_version('Playerctl', '2.0')
from gi.repository import Playerctl, GLib
from typing import List, Self
from argparse import ArgumentParser
import json
import sys

parser = ArgumentParser()
parser.add_argument("-l", "--main-loop", action="store_true")
parser.add_argument("-p", "--play-pause", action="store_true")
parser.add_argument("-N", "--next", action="store_true")
parser.add_argument("-P", "--previous", action="store_true")
args = parser.parse_args()


PLAY_ICON  = "  "
PAUSE_ICON = "  "

manager = Playerctl.PlayerManager()


class json_data(dict):
    def __init__(self) -> None:
        super().__init__()
        self["text"] = ""
        self["alt"] = ""
        self["tooltip"] = ""
        self["icon"] = ""
    def print(self, data=(), **kwargs) -> Self:
        super().update(data, **kwargs)
        out = {
                "text": str(self.get("icon")) + str(self.get("text")),
                "alt": self["alt"],
                "tooltip": self["tooltip"]
                }
        sys.stdout.write(json.dumps(out) + '\n')
        sys.stdout.flush()
        return self

jdata: json_data = json_data()


def on_play(player, status, manager):
    global jdata
    jdata.print({"icon": PLAY_ICON})


def on_pause(player, status, manager):
    global jdata
    jdata.print({"icon":  PAUSE_ICON})


def on_metadata(player, metadata, manager):
    global jdata
    keys = metadata.keys()
    if 'xesam:artist' in keys and 'xesam:title' in keys:
        jdata.print(
            {
                "text": f'{metadata['xesam:artist'][0]} - {metadata['xesam:title']}',
                "alt": metadata['xesam:title'],
                "tooltip": f'{', '.join(metadata['xesam:artist'])} - {metadata['xesam:title']}'
            }
        )


def init_player(name):
    if name.name in ['spotify']:
        player = Playerctl.Player.new_from_name(name)
        player.connect('playback-status::playing', on_play, manager)
        player.connect('playback-status::paused', on_pause, manager)
        player.connect('metadata', on_metadata, manager)
        manager.manage_player(player)


def on_name_appeared(manager, name):
    init_player(name)


def on_player_vanished(manager, player):
    jdata.print({"text": "", "icon": ""})


def get_spotify() -> Playerctl.Player | None:
    for name in manager.props.player_names:
        if name.name in ['spotify']:
            return Playerctl.Player.new_from_name(name)


def main_loop():
    manager.connect('name-appeared', on_name_appeared)  
    manager.connect('player-vanished', on_player_vanished)
    
    for name in manager.props.player_names:
        init_player(name)

    if spotify := get_spotify():
        jdata.print(
            {
                "text": f'{spotify.get_artist()} - {spotify.get_title()}',
                "alt": spotify.get_title(),
                "tooltip": f'{spotify.get_artist()} - {spotify.get_title()}'
            }
        )
        if spotify.props.status == "Playing":
            jdata.print({"icon":  PLAY_ICON})
        else:
            jdata.print({"icon":  PAUSE_ICON})
    else:
        jdata.print({"text": "", "percentage": 0})

    
    main = GLib.MainLoop()
    main.run()


def play_pause():
    if spotify := get_spotify():
        spotify.play_pause()


def next():
    if spotify := get_spotify():
        spotify.next()


def previous():
    if spotify := get_spotify():
        spotify.previous()


if args.main_loop:
    try:
        main_loop()
    except KeyboardInterrupt:
        exit(0)
    exit(1)

if args.play_pause:
    play_pause()
    exit(0)

if args.next:
    next()
    exit(0)

if args.previous:
    previous()
    exit(0)