#!/usr/bin/env python3
# -*- mode: python; coding: utf-8 -*-

"""
Communicate with Telldus Live server.

Usage:
  tellduslive.py (-h | --help)
  tellduslive.py --version
  tellduslive.py [-v|-vv] [options] list [-r] [-d <DELAY>]
  tellduslive.py [-v|-vv] [options] <id> (on|off)

Options:
  -H <host>         Host
  -L <config.yml>   Config file for local telsticknet 
  -D                Autodiscover host
  -r                Repeat polling until stopped
  -d <DELAY>        Delay between polling [default: 5]
  -h --help         Show this message
  -v,-vv            Increase verbosity
  --version         Show version

"""

import docopt
import logging
from sys import stderr
from time import sleep

from tellduslive import (__version__, read_credentials, Session,
                         TURNON, TURNOFF, UP, DOWN,
                         BATTERY_LOW, BATTERY_OK, BATTERY_UNKNOWN)

_LOGGER = logging.getLogger(__name__)

LOGFMT = "%(asctime)s %(levelname)5s %(threadName)10s %(name)40s %(message)s"
DATEFMT = "%H:%M.%S"

STR_STATES = {
    TURNON: 'On',
    TURNOFF: 'Off',
    UP: 'Up',
    DOWN: 'Down',
}

def str_batt(battery):
    if battery == BATTERY_LOW:
        return '\u2713'
    elif battery == BATTERY_UNKNOWN:
        return ''
    elif battery == BATTERY_OK:
        return '\u2713'
    elif battery == None:
        return ''
    else:
        return battery

def main():
    """Command line interface."""
    args = docopt.docopt(__doc__,
                         version=__version__)

    if args['-v'] == 2:
        level=logging.DEBUG
    elif args['-v']:
        level=logging.INFO
    else:
        level=logging.ERROR

    try:
        import coloredlogs
        coloredlogs.install(level=level,
                            stream=stderr,
                            datefmt=DATEFMT,
                            fmt=LOGFMT)
    except ImportError:
        _LOGGER.debug("no colored logs. pip install coloredlogs?")
        logging.basicConfig(level=level,
                            stream=stderr,
                            datefmt=DATEFMT,
                            format=LOGFMT)

    credentials = read_credentials()

    if args['-D']:
        try:
            from tellsticknet.discovery import discover
        except ImportError:
            exit('Could not import tellsticknet library')
        host = next(discover(), None)
        if not host:
            exit('Could not find local Tellstick Net or Tellstick ZNet')
        _LOGGER.debug('Found Tellstick at %s', host)
        credentials.update(host = host)
    elif args['-H']:
        credentials.update(host = args['-H'])
    if args['-L']:
        import yaml
        config_file = args['-L']
        _LOGGER.debug("tellstik config file = %s", config_file)
        with open(config_file, 'r') as stream:
            try:
                _config = yaml.load(stream)
            except yaml.YAMLError as exc:
                print(exc)
        credentials.update(config = _config)
  

    def list_devices():
        print('Devices')
        print('-' * 90)
        for device in sorted(session.devices,
                             key=lambda d: d.is_sensor):
            if device.is_sensor:
                for item in device.items:
                    print('Sensor {id:>8} {id2:>3} {device.protocol:>10} {device.model:<19} '
                          '{device.name:<20} {item.name:>8} {item.value:>5} {battery}'.format(
                              id=device.device_id[1:],  # FIXME: Remove hack
                              id2=device.sensorId,
                              device=device,
                              battery=str_batt(device.battery),
                              item=item))
            else:
                print('Device {device.device_id:>8} {space:<34} '
                      '{device.name:<20} {state:>14} {battery}'.format(
                          device=device,
                        space='',
                          battery=str_batt(device.battery),
                          state=STR_STATES.get(device.state, '?')))

    def callback(device):
        #_LOGGER.info('Got asynchronous sensor update for %s', device.name)
        list_devices()
        
    credentials.update(listen=args['-r'],
                       callback=callback)

    try:
        session = Session(**credentials)
    except ValueError as e:
        exit(e)

    if not session.update():
        exit('Could not update status from server')
    if args['list']:
        while True:
            list_devices()
            
            if not args['-r']:
                exit(0)

            sleep(int(args['-d']))
            session.update()

    elif args['<id>']:
        device_id = args['<id>']
        device = session.device(device_id)
        if args['on']:
            device.turn_on()
        elif args['off']:
            device.turn_off()

if __name__ == '__main__':
   main()
