# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.



'''
Created on Aug 2, 2010

'''


import sys
import os
import inspect
from optparse import OptionParser, OptParseError, BadOptionError, OptionError, OptionConflictError, OptionValueError
import cloudapis as apis


def describe(name,desc):
    def inner(decoratee):
        if not hasattr(decoratee,"descriptions"): decoratee.descriptions = {}
        decoratee.descriptions[name] = desc
        return decoratee
    return inner


def error(msg):
    sys.stderr.write(msg)
    sys.stderr.write("\n")


class MyOptionParser(OptionParser):
    def error(self, msg):
        error("%s: %s\n" % (self.get_prog_name(),msg))
        self.print_usage(sys.stderr)
        self.exit(os.EX_USAGE)

    def parse_args(self,*args,**kwargs):
        options,arguments = OptionParser.parse_args(self,*args,**kwargs)

        def prune_options(options,alist):
            """Given 'options' -- a list of arguments to OptionParser.add_option,
            and a set of optparse Values, return a dictionary of only those values
            that apply exclusively to 'options'"""
            return dict( [ (k,getattr(options,k)) for k in dir(options) if k in alist ] )

        api_options = prune_options(options,self.api_dests)
        cmd_options = prune_options(options,self.cmd_dests)

        return options,arguments,api_options,cmd_options


def get_parser(api_callable=None,cmd_callable=None): # this should probably be the __init__ method of myoptionparser

    def getdefaulttag(default):
        if default is not None: return " [Default: %default]"
        return ''

    def get_arguments_and_options(callable):
        """Infers and returns arguments and options based on a callable's signature.
        Cooperates with decorator @describe"""
	try:
        	funcargs = inspect.getargspec(callable).args
        	defaults = inspect.getargspec(callable).defaults
	except:
		funcargs = inspect.getargspec(callable)[0]
        	defaults = inspect.getargspec(callable)[3]
        if not defaults: defaults = []
        args = funcargs[1:len(funcargs)-len(defaults)] # this assumes self, so assumes methods
        opts = funcargs[len(funcargs)-len(defaults):]
        try: descriptions = callable.descriptions
        except AttributeError: descriptions = {}
        arguments = [ (argname, descriptions.get(argname,'') ) for argname in args ]
        options = [ [
                          ("--%s"%argname.replace("_","-"),),
                          {
                           "dest":argname,
                           "help":descriptions.get(argname,'') + getdefaulttag(default),
                           "default":default,
                          }
                        ] for argname,default in zip(opts,defaults) ]
        return arguments,options

    basic_usage = "usage: %prog [options...] "

    api_name = "<api>"
    cmd_name = "<command>"
    description = "%prog is a command-line tool to access several cloud APIs."
    arguments = ''
    argexp = ""

    if api_callable:
        api_name = api_callable.__module__.split(".")[-1].replace("_","-")
        api_arguments,api_options = get_arguments_and_options(api_callable)
        assert len(api_arguments) is 0 # no mandatory arguments for class initializers

    if cmd_callable:
        cmd_name = cmd_callable.__name__.replace("_","-")
        cmd_arguments,cmd_options = get_arguments_and_options(cmd_callable)
        if cmd_arguments:
            arguments   = " " + " ".join( [ s[0].upper() for s in cmd_arguments ] )
            argexp = "\n\nArguments:\n" + "\n".join ( "  %s\n                        %s"%(s.upper(),u) for s,u in cmd_arguments )
        description = cmd_callable.__doc__

    api_command = "%s %s"%(api_name,cmd_name)

    if description: description = "\n\n" + description
    else: description = ''

    usage = basic_usage + api_command + arguments + description + argexp

    parser = MyOptionParser(usage=usage, add_help_option=False)

    parser.add_option('--help', action="help")

    group = parser.add_option_group("General options")
    group.add_option('-v', '--verbose', dest="verbose", help="Print extra output")

    parser.api_dests = []
    if api_callable and api_options:
        group = parser.add_option_group("Options for the %s API"%api_name)
        for a in api_options:
            group.add_option(a[0][0],**a[1])
            parser.api_dests.append(a[1]["dest"])

    parser.cmd_dests = []
    if cmd_callable and cmd_options:
        group = parser.add_option_group("Options for the %s command"%cmd_name)
        for a in cmd_options:
            group.add_option(a[0][0],**a[1])
            parser.cmd_dests.append(a[1]["dest"])

    return parser

def lookup_command_in_api(api,command_name):
    command = getattr(api,command_name.replace("-","_"),None)
    return command

def get_api_list(api):
	apilist = []
	for cmd_name in dir(api):
		cmd = getattr(api,cmd_name)
            	if callable(cmd) and not cmd_name.startswith("_"):
			apilist.append(cmd_name)
	return apilist

def get_command_list(api):
        cmds = []
        for cmd_name in dir(api):
            cmd = getattr(api,cmd_name)
            if callable(cmd) and not cmd_name.startswith("_"):
		if cmd.__doc__:docstring = cmd.__doc__
		else:docstring = ''
		cmds.append( "    %s" % (cmd_name.replace('_','-')) )
        return cmds
