#!/usr/bin/env python3

import click
import sys
import os
import yaml
# telnet is the only protocol supported by the squeezebox server
from telnetlib import Telnet    # nosec
from tabulate import tabulate
import squeezebox_cli.player
import squeezebox_cli.database
import squeezebox_cli.display

sb_server = None
player_id = None


@click.group()
@click.option(
        '--host', type=str,
        help='hostname for squeezebox server')
@click.option(
        '--port', type=int,
        help='port for squeezebox server (default 9090)')
def squeezebox(host, port):
    try:
        with open(os.path.expanduser('~/.squeezebox-cli.yaml')) as f:
            cfg = yaml.safe_load(f)
            if not host:
                try:
                    host = cfg['server']['host']
                except KeyError:
                    pass
            if not port:
                try:
                    port = cfg['server']['port']
                except KeyError:
                    pass
    except FileNotFoundError:
        pass
    if not port:
        port = 9090
    global sb_server
    sb_server = Telnet(host, port)
    if not sb_server.sock:
        click.echo(f'ERROR: could not connect to {host}:{port}')
        sys.exit(1)


@squeezebox.command(help='list the currently connected players')
def players():
    # TODO: options for columns to show?
    ps = squeezebox_cli.player.list_all(sb_server)
    click.echo(tabulate(
        [(p['playerindex'], p['name'], 'yes' if p['isplaying'] else 'no')
            for p in ps],
        headers=['index', 'name', 'is playing?']))


@squeezebox.command(help='search the music database')
@click.argument('term')
def search(term):
    reply = squeezebox_cli.database.search(sb_server, term)
    artists = reply['artists']
    click.echo(tabulate(
        [(artist, id) for id, artist in artists.items()],
        headers=['artist', 'id']))
    click.echo()
    albums = reply['albums']
    click.echo(tabulate(
        [(album, id) for id, album in albums.items()],
        headers=['album', 'id']))
    click.echo()
    tracks = reply['tracks']
    click.echo(tabulate(
        [(track, id) for id, track in tracks.items()],
        headers=['track', 'id']))


@squeezebox.group(help='view and control a player by name or index')
@click.argument('player-name')
def player(player_name):
    global player_id
    player_id = squeezebox_cli.player.id_from_index_or_name(
            sb_server, player_name)
    if not player_id:
        click.echo(f'ERROR: no such player: {player_name}')
        sys.exit(1)


@player.command(help='stop the specified player')
def stop():
    squeezebox_cli.player.stop(sb_server, player_id)


@player.group(help='play a track or album')
def play():
    pass


@play.command(help='play the specified track')
@click.argument('track_id', type=int)
def track(track_id):
    squeezebox_cli.player.play(sb_server, player_id, track_id=track_id)


@play.command(help='play the specified album')
@click.argument('album_id', type=int)
def album(album_id):
    squeezebox_cli.player.play(sb_server, player_id, album_id=album_id)


@player.command(help='pause/unpause the specified player')
def pause():
    squeezebox_cli.player.pause(sb_server, player_id)


@player.command(help='status of the specified player')
@click.option(
        '--long/--short', default=False,
        help='verbose output, playlist etc.')
@click.option(
        '--listen/--return', default=False,
        help='listen for and display notificataions')
@click.option('--max-tracks', type=int)
def status(long, listen, max_tracks):
    status = squeezebox_cli.player.status(sb_server, player_id)
    click.echo(squeezebox_cli.display.format_status(status))
    if long:
        click.echo(squeezebox_cli.display.format_playlist(
            [squeezebox_cli.database.songinfo(sb_server, id)
             for id, t in status['playlist']],
            status['playlist_cur_index'],
            max_tracks))
    if listen:
        for n in squeezebox_cli.player.listen(
                Telnet(sb_server.host, sb_server.port), status['playerid']):
            # click.echo(n)
            for handler in squeezebox_cli.player.notification_handlers:
                if handler(status, n, sb_server):
                    click.echo(squeezebox_cli.display.format_status(status))
                    if long:
                        click.echo(squeezebox_cli.display.format_playlist(
                            [squeezebox_cli.database.songinfo(sb_server, id)
                             for id, t in status['playlist']],
                            status['playlist_cur_index'],
                            max_tracks))
                    break


@player.command(help='play the next track in the current playlist')
def next():
    squeezebox_cli.player.next(sb_server, player_id)


@player.command(help='play the previous track in the current playlist')
def previous():
    squeezebox_cli.player.previous(sb_server, player_id)


@player.group(help=('add a track or album to the end of the current playlist'))
def add():
    pass


@add.command(help='add a track to the end of the current playlist')
@click.argument('track_id')
def track(track_id):
    squeezebox_cli.player.playlist_add(sb_server, player_id, track_id=track_id)


@add.command(help='add an album to the end of the current playlist')
@click.argument('album_id')
def album(album_id):
    squeezebox_cli.player.playlist_add(sb_server, player_id, album_id=album_id)


@player.command(help='set or change the player volume N, +N or -- -N')
@click.argument('vol', type=str)
def volume(vol):
    squeezebox_cli.player.set_volume(sb_server, player_id, vol)


@player.command(help='remove a track from the current playlist by index')
@click.argument('index', type=int)
def remove(index):
    squeezebox_cli.player.playlist_remove(sb_server, player_id, index)


if __name__ == '__main__':
    squeezebox()
