#!/usr/bin/env python 

"""
Pegasus - focus-server 

High level control of the pegasus focus server 
"""

import sys
import os, os.path 
import time 
import datetime

import logging 
import inspect 
import xmlrpclib
from SimpleXMLRPCServer import SimpleXMLRPCServer, list_public_methods

# from pegasus.PegasusSerial import Focuser, DummyFocuser 
from pegasus import Focuser, DummyFocuser 

# DEFAULT_HOSTNAME = "127.0.0.1"
DEFAULT_HOSTNAME = "192.168.130.178"
DEFAULT_PORT = 8840
SERVER_HOSTNAME = os.getenv("FOCUS_SERVER_HOSTNAME", DEFAULT_HOSTNAME)
SERVER_PORT = int(os.getenv("FOCUS_SERVER_PORT", DEFAULT_PORT))


class FocusServer(SimpleXMLRPCServer):
    
    def serve_forever(self):
        self.quit = 0
        while not self.quit:
            self.handle_request()

def server_quit():
    logging.info("Exiting. Bye.")
    server.quit = 1
    return 1


# def open_server():
#     global focuser
#     try:
#         focuser = Focuser()
#     except:
#         return False
#     return True


# ======================================================================
# daemonization related stuff
def redirect_stream(system_stream, target_stream):
    if target_stream is None:
        target_fd = os.open(os.devnull, os.O_RDWR)
    else:
        target_fd = target_stream.fileno()
    os.dup2(target_fd, system_stream.fileno())


def daemonize(options, args):
    try:
        pid = os.fork()
        if pid > 0:
            # first parent exits
            sys.exit(0)
    except OSError as e:
        print >>sys.stderr, 'fork #1 failed: %d (%s)' % (e.errno, e.strerror)
        sys.exit(1)
    os.setsid()
    
    try:
        pid = os.fork()
        if pid > 0:
            # exit from second parent 
            print "starting server as daemin with PID %d" % pid
            sys.exit(0)
    except OSError as e:
        print >>sys.stderr, "fork #2 failed %d (%s)" % (e.errno, e.strerror)
        sys.exit(1)
        
    main(options, args)
# ======================================================================


# ======================================================================
def main(options, args):
    logging.basicConfig(filename=options.log_file, 
                        level=logging.DEBUG, 
                        format='%(asctime)s: focus-server: %(message)s')
    redirect_stream(sys.stdin, None)
    redirect_stream(sys.stdout, None)
    redirect_stream(sys.stderr, None)
        
    #    server.register_function(focuser_instance.open_server, "open")
    server.register_function(server_quit, "quit")
    server.register_function(focuser_instance.is_ok, "is_ok")
    server.register_function(focuser_instance.stop, "stop")
    server.register_function(focuser_instance.current_position, "current_position")
    server.register_function(focuser_instance.set_position, "set_position")
    server.register_function(focuser_instance.is_stepping, "is_stepping")
    server.register_function(focuser_instance.move, "move")
    server.register_function(focuser_instance.get_temperature, "get_temperature")
    server.register_function(focuser_instance.invert_pins, "invert_pins")
    server.register_function(focuser_instance.set_max_speed, "set_max_speed")
    server.register_function(focuser_instance.get_version, "get_version")
    server.register_function(focuser_instance.get_allinfo, "get_allinfo")
    server.register_function(focuser_instance.go, "go")
    server.register_function(focuser_instance.throttle_led, "throttle_led")
    
    server.register_function(focuser_instance._listMethods, "__dir__")
    server.register_function(focuser_instance._listMethods, "system.listMethods")
    server.register_function(focuser_instance._listMethods, "trait_names")
    server.register_function(focuser_instance._listMethods, "_getAttributeNames")
    server.register_function(focuser_instance._methodHelp, "system.methodHelp")

    logging.info("server going up.")
    server.serve_forever()
    
    
if __name__ == "__main__":
    now = datetime.datetime.now()
    logdir = os.path.join(os.getenv("HOME", "logs"))
    logname = os.path.join(logdir, 
                           'focus-server-%s.log' % now.date().isoformat())
    logsymlink = os.path.join(logdir, "focus-server.log")
    if os.path.islink(logsymlink):
        try:
            os.unlink(logsymlink)
            os.symlink(logname, logsymlink)
        except OSError:
            pass

    import optparse 
    parser = optparse.OptionParser(usage="%prog [-l log] [-d]")
    parser.add_option('-d', '--daemon', default=False, 
                      action='store_true', 
                      help='Run as a background daemon')
    parser.add_option('--dummy', default=False, 
                      action='store_true', 
                      help='Run a fake instance instead')
    parser.add_option('-p', '--port', default=SERVER_PORT, 
                      action='store', type='int', 
                      help='Listen on port')
    parser.add_option('-H', '--hostname', default=SERVER_HOSTNAME, 
                      action='store', 
                      help='server address')
    parser.add_option('-l', '--log-file', default=logname, 
                      action='store', 
                      help='specify a log file')
    parser.add_option('-t', '--tty', default='/dev/pegasus', 
                      dest='tty', action='store', 
                      help='specify the serial port')
    (options, args) = parser.parse_args()
    
    SERVER_HOSTNAME = options.hostname
    SERVER_PORT = options.port    


    if options.dummy:
        focuser_instance = DummyFocuser(port=options.tty)
    else:
        focuser_instance = Focuser(port=options.tty)
    server = FocusServer((SERVER_HOSTNAME, SERVER_PORT))
    
    if options.daemon:
        daemonize(options, args)
    else:
        main(options, args)

        
