#!/usr/bin/python

from subprocess import check_output, check_call, CalledProcessError, call
import re
import xmlrpclib
import time
import os
import sys

power_query = re.compile("powerState is ([12])")
com = ["sshpass", "-p", "skydice", "ssh", "admin@raritan"]
devices = { 'laser': '1',
            'pc104': '2',
            'sbig': '3',
            'pulsar': '4',
            'pegasus': '5'}

def device_status(device):
    a = check_output(com + ["show /system1/outlet"+devices[device]])
    return {'1' : 'on', '2': 'off'}[power_query.findall(a)[0]]

def turn(device, on):
    stat = "on" if on else "off"
    print check_output(com + ["set /system1/outlet%s powerState=%s" % (devices[device] , stat)])

def probe_pc104():
    try:
        check_call(["ssh", "dice@dicetel", "echo $HOSTNAME"])
        return True
    except CalledProcessError:
        return False

def launch_pc104():
    if probe_pc104():
        print "PC104 already on"
        return True
    print "Ensuring the PC104 power is off ..."
    turn("pc104", False)
    time.sleep(10)
    print "Turning on PC104 power"
    turn("pc104", True)
    while not probe_pc104():
        print "Waiting for boot ..."
        time.sleep(10)
    print "PC104 ready!"
    return True

def shutdown_pc104():
    on = probe_pc104()
    if on:
        print "Shutting down PC104 ..."
        call(["ssh", "dice@dicetel", "sudo halt"])
        while on:
            on = probe_pc104()
            time.sleep(10)
        print "PC104 off"
        return True
    else:
        print "PC104 already turned off"
        return True

if __name__ == "__main__":
    import argparse
    parser = argparse.ArgumentParser(description='''Control of telescope devices

Exemples:
Check system status:
dicepower status

Turn on the system:
dicepower on

System shutdown:
dicepower off

Turn on one element:
dicepower device pulsar on
    ''', formatter_class=argparse.RawDescriptionHelpFormatter)
    parser.add_argument('command', metavar='command', nargs='+',
                        help='command to execute : on|off|status|device')
    
    args = parser.parse_args()
    if args.command[0] == 'status':
        for device in devices:
            print '%s : %s' % (device, device_status(device))
            time.sleep(1)
    elif args.command[0] == 'on':
        launch_pc104()
        turn('pegasus', True)
        turn('pulsar', True)
        turn('sbig', True)
    elif args.command[0] == 'off':
        turn('pegasus', False)
        turn('pulsar', False)
        turn('sbig', False)
        shutdown_pc104()
        print 'Extra wait for PC104 complete shutdown'
        time.sleep(60)
        turn('pc104', False)
    elif args.command[0] == 'device':
        if (len(args.command) != 3) or (args.command[1] not in devices) or (args.command[2] not in ['on','off']):
            print 'Command device needs a device among %s and an action in "on|off"' % str(devices.keys())
            parser.print_help()
        turn(args.command[1], args.command[2] == 'on')
    else:
        print "Unknown command : " + args.command[0]
        parser.print_help()
        sys.exit(-1)
