#! /usr/bin/env python
# -*- coding: iso-8859-1 -*-

# chimera - observatory automation system
# Copyright (C) 2006-2007  P. Henrique Silva <henrique@astro.ufsc.br>

# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.

# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.

import sys
import os
import time
import logging
import signal

from optparse import OptionParser, OptionGroup

from chimera.core.manager import Manager
from chimera.core.version import _chimera_version_, _chimera_description_

from chimera.instruments.focuser import Focuser
from chimera.util.enum import Enum

from chimera.core.exceptions import ObjectNotFoundException
from chimera.core.exceptions import ChimeraObjectException
from chimera.core.exceptions import InvalidLocationException
from chimera.core.exceptions import ClassLoaderException

from chimera.core.location import Location

from chimera.core.callback import callback

from chimera.core.log import setConsoleLevel
#setConsoleLevel(logging.DEBUG)
setConsoleLevel(1e9)

if __name__ == '__main__':

    chimera_focus_description = " - Focuser controller"

    def check_includepath (option, opt_str, value, parser):
        if not value or not os.path.isdir (os.path.abspath(value)):
            raise optparse.OptionValueError ("Couldn't found %s include path." % value)
        eval ('parser.values.%s.append ("%s")' % (option.dest, value))

    def check_location (option, opt_str, value, parser):
        try:
            l = Location (value)
        except InvalidLocationException:
            raise optparse.OptionValueError ("%s isnt't a valid location." % value)

        eval ('parser.values.%s.append ("%s")' % (option.dest, value))


    parser = OptionParser(prog="chimera-focus", version=_chimera_version_,
                          description=_chimera_description_+chimera_focus_description)

    config = OptionGroup(parser, "Focuser and driver configuration")

    config.add_option("-f", "--focuser", action="callback", type="string", dest="focuser",
                      help="Focuser instrument to be used. If blank, create a new"
                      " focuser instance, using the the driver selected with --driver."
                      " format: [host:port]/Class/name. [default=\"\"]",
                      callback=check_location)

    config.add_option("-d", "--driver", action="callback", type="string", dest="driver",
                      help="Focuser driver to be used."
                      " /Class/name?option1=value1,option2=value. [default=%default]",
                      callback=check_location)

    config.add_option("-D", "--drivers-dir", action="callback", callback=check_includepath,
                      dest="drv_dir", type="string",
                      help="Append PATH to drivers load path.",
                      metavar="PATH")

    actions = OptionGroup(parser, "Actions")
    
    actions.add_option("--in", action="store", type="int", dest="move_in",
                      help="Move N steps IN", metavar="N")

    actions.add_option("--out", action="store", type="int", dest="move_out",
                      help="Move N steps OUT", metavar="N")

    actions.add_option("--to", action="store", type="int", dest="move_to",
                      help="Move to POSITION", metavar="POSITION")

    actions.add_option("-i", "--info", action="store_true", dest="info",
                      help="Print focuser information and exit")

    parser.add_option("-q", "--quiet", action="store_true", dest='quiet',
                      help="Don't display informations while working [default=%default].")

    parser.add_option_group(config)
    parser.add_option_group(actions)    


    prefix = os.path.realpath(os.path.join(os.path.abspath(__file__), '../../chimera/'))
    drivers_path = [os.path.join(prefix, 'drivers')]

    parser.set_defaults(focuser= [],
                        driver   = ["/OptecTCFS/optec?device=/dev/ttyS4"],
                        drv_dir  = [],
                        quiet    = False,
                        info     = False,
                        move_in  = None,
                        move_out = None,
                        move_to  = None)


    options, args = parser.parse_args(sys.argv)

    Action = Enum("IN", "OUT", "TO")

    action = None
    steps  = None

    # some validations
    if options.move_in != None:
        action = Action.IN
        steps  = options.move_in
        
        if (options.move_out != None) or (options.move_to != None):
            print >> sys.stderr, "Cannot use --in with --out/--to"
            sys.exit(1)

    if options.move_out != None:
        action = Action.OUT
        steps  = options.move_out

        if (options.move_in != None) or (options.move_to != None):
            print >> sys.stderr, "Cannot use --out with --in/--to"
            sys.exit(1)

    if options.move_to != None:
        action = Action.TO
        steps  = options.move_to

        if (options.move_in != None) or (options.move_out != None):
            print >> sys.stderr, "Cannot use --to with --in/--out"
            sys.exit(1)

    if not action and not options.info:
        print >> sys.stderr, "Please, ask me anything to do. Try --in/--out/--to."
        sys.exit(1)
 
    # 
    # start
    #

    manager = Manager(port=12000)

    focuser = None

    # ctrl+c handling
    aborted = False

    def sighandler(self, sig = None, frame = None):

        global aborted
        
        if aborted == False:
            aborted = True
        else:
            return
            
    signal.signal(signal.SIGTERM, sighandler)
    signal.signal(signal.SIGINT, sighandler)

    # use an already running focuser
    if options.focuser:
        try:
            focuser = manager.getProxy(options.focuser[0])
        except (ObjectNotFoundException, ClassLoaderException), e:
            print >> sys.stderr, "Cannot find focuser %s. (%s)" % (options.focuser[0], e)
            manager.shutdown()
            sys.exit(1)
        except (ChimeraObjectException), e:
            print >> sys.stderr, "Problems starting focuser %s. (%s)" % (options.focuser[0], e)
            manager.shutdown()
            sys.exit(1)

    # create a new focuser using selected driver
    else:
        try:
            driver = manager.addLocation(options.driver[-1], path=drivers_path)
            focuser = manager.addClass(Focuser, "tel", {"driver": options.driver[-1]})
        except (ObjectNotFoundException, ClassLoaderException), e:
            print >> sys.stderr, "Cannot find focuser driver %s. (%s)" % (options.driver[-1],e)
            manager.shutdown()
            sys.exit(1)
        except (ChimeraObjectException), e:
            print >> sys.stderr, "Problems starting focuser driver %s. (%s)" % (options.driver[-1], e)
            manager.shutdown()
            sys.exit(1)
    
    # move
    start = time.time()

    try:

        if options.info:
            print "Focuser: %s (%s)" % (options.driver[-1], driver["device"])
            print "Current focuser position:", focuser.getPosition()

        else:
            
            try:
                if action == Action.IN:
                    print "Moving %d steps IN ... " % steps,
                    focuser.moveIn(steps)
                elif action == Action.OUT:
                    print "Moving %d steps OUT ... " % steps,
                    focuser.moveOut(steps)
                else:
                    print "Moving to %d ... " % steps,
                    focuser.moveTo(steps)
                    
                print "OK (took %.3fs)" % (time.time()-start)

            except Exception, e:
                print >> sys.stderr, "Error trying to move focuser. (%s)" % e

    finally:

        manager.shutdown()
        time.sleep(1)
        sys.exit(0)
