#!/usr/bin/env python

""" PySqueezeCenter Command Line Tool """

__revision__ = "$Id$"
__docformat__ = 'restructuredtext en'

import os, sys, logging, optparse

from pysqueezecenter.server import Server
from pysqueezecenter.utils import clean_command

# Globals

PROJECT = "PySqueezeCenter"
VERSION = "0.94"

logger = logging.getLogger(__name__)
LOG_HELP = ','.join(["%d=%s" % (4-x, logging.getLevelName((x+1)*10)) for x in xrange(5)])
LOG_FORMAT_CONS = '%(levelname)s: %(message)s'
LOG_FORMAT_FILE = '%(asctime)s %(name)s[%(process)d] %(levelname)10s %(message)s'
LOGLEVEL_DICT = { 1 : 50, 2:40, 3:20, 4:10, 5:1 }
DEFAULT_VERBOSITY = 3

VALID_COMMANDS = ["play", "stop", "pause", "unpause", "toggle", "next", "prev",
                  "volume_up", "volume_down", "mute", "unmute", "seek_to",
                  "forward", "rewind", "set_power_state", "set_volume", "show", "display", "infos",
                  "get_ref", "get_uuid", "get_name", "get_ip_address", "get_model", "get_display_type",
                  "get_wifi_signal", "get_mode", "get_time_elapsed", "get_time_remaining", "get_power_state",
                  "get_ir_state", "get_volume", "get_bass", "get_treble", "get_pitch", "get_rate", "get_muting",
                  "get_track_genre", "get_track_artist", "get_track_album", "get_track_title",
                  "get_track_duration", "get_track_remote", "get_track_current_title", "get_track_path"]

# Option Parsing

parser = optparse.OptionParser(usage="%prog or type %prog -h (--help) for help", description=__doc__, version=PROJECT + " v" + VERSION)

parser.add_option("-v", action="count", dest="verbosity", default=DEFAULT_VERBOSITY, help="Verbosity. Add more -v to be more verbose (%s) [default: %%default]" % LOG_HELP)
parser.add_option("-l", "--logfile", dest="logfile", default=None, help = "Log to file instead of console" )
parser.add_option("-s", "--host", dest="host", default="localhost", help="Specify Hostname of SqueezeCenter [default: %default]")
parser.add_option("-n", "--port", dest="port", default="9090", help="Specify Port of SqueezeCenter [default: %default]")
parser.add_option("-u", "--username", dest="username", default=None, help="Specify Authorisation Username")
parser.add_option("-p", "--password", dest="password", default=None, help="Specify Authorisation Password")
parser.add_option("-d", "--device", dest="device", default=None, help="Specify SqueezePlayer Device MAC Address")
parser.add_option("-i", "--info", dest="info", action="store_true", default=False, help="Show Server/Player Information")
parser.add_option("-r", "--raw", dest="raw", action="store_true", default=False, help="Output only minimal raw results (useful for scripts)")
parser.add_option("-q", "--quick", dest="quick", action="store_true", default=False, help="Perform a quick one-time action (does not query current device state)")


(options, args) = parser.parse_args()

# Logging Setup

verbosity = LOGLEVEL_DICT.get(int(options.verbosity), DEFAULT_VERBOSITY)

if options.logfile is None:
    logging.basicConfig(level=verbosity, format=LOG_FORMAT_CONS)
else:
    logfilename = os.path.normpath(options.logfile)
    logging.basicConfig(level=verbosity, format=LOG_FORMAT_FILE, filename=logfilename, filemode='a')
    print >> sys.stderr, "Logging to %s" % logfilename

# Main

sc = Server(hostname=options.host, port=options.port, username=options.username, password=options.password)
sc.logger = logger

update_mode = not options.quick

if options.info:
    update_mode = True

try:
    sc.connect(update=update_mode)
except:
    logger.error("Cannot connect to SqueezeCenter (%s:%s)" % (options.host, options.port))
    sys.exit(1)

all_players = sc.players

if options.info:
    logger.info("SqueezeCenter Version: %s" % (sc.get_version()))
    for p in all_players:
        logger.info("Player: %s | %s | V: %i | M: %s | T: %s | C: %s | W: %s" % (p.ref, p.name, p.get_volume(), p.get_mode(), p.get_time_elapsed(), p.is_connected, p.get_wifi_signal_strength()))

players = []
if options.device == 'all':
    players = list(all_players)
else:
    sel_player = sc.get_player(options.device)
    if sel_player:
        players.append(sel_player)

if options.device and len(players)==0:
    logger.error("Cannot find player %s" % (options.device))
    sys.exit(1)

if not args:
    logger.warn("No arguments provided")
    sys.exit(0)

command_map = {}

for c in VALID_COMMANDS:
	cleaned = clean_command(c)
	command_map[cleaned] = c

cmd = clean_command(args[0])

try:
    params = args[1:]
except IndexError:
    params = []

raw_cmd = command_map.get(cmd)

for player in players:
    if player is not None:
        if cmd in command_map:
            func = getattr(player, raw_cmd, None)
            try:
                logger.debug("%s: %s [%s]" % (player.name, raw_cmd.upper(), ", ".join(params)))
                result = func(*params)
                if options.raw:
                    if result is not None:
                        print result
                else:
                    if result is None:
                        result = "No Output"
                    logger.info("[%s] %s" % (raw_cmd, result))            
            except ValueError:
                logger.error("Invalid parameter")
            except TypeError:
                logger.error("Incorrect number of parameters or invalid type parameter")
        else:
            logger.error("Invalid command or no device: %s" % (cmd))

