#!/usr/bin/env python3

import sys, sak, inspect, lib.pacman, lib.error, lib.check, lib.args, lib.str , lib.fn


def main ( inp ) :

	hierarchy, action, inp = findaction( sak , inp , ['sak'] )
	args, kwargs = assignarguments( hierarchy, action, inp )
	action( *args, **kwargs )


def findaction ( module , inp , hierarchy ) :

	# DETERMINE MODULE

	i = 0

	while True :

		parent = '.'.join(hierarchy)

		lib.check.ModuleOrActionNameSpecified( parent , module , inp , i )
		moduleName = inp[i]

		modules = lib.pacman.resolve( moduleName , module )

		lib.check.ModuleOrActionNameExists( parent, module , moduleName , modules )
		lib.check.ModuleOrActionNameNotAmbiguous( parent, moduleName, modules )

		moduleName = modules[0]
		module = getattr( module , moduleName )

		hierarchy.append( moduleName )

		i += 1

		if lib.fn.callable( module ) : break

	return hierarchy , module , inp[i:]


def assignarguments ( hierarchy, action, inp ) :

	# CHECK ACTION ARGUMENTS

	moduleName = ".".join( hierarchy[:-1] )
	actionName = hierarchy[-1]

	args, kwargs = lib.args.parse( inp, [], {} )

	spec = inspect.getargspec( action )

	kwargslist = lib.args.kwargslist( spec )

	if kwargs :

		lib.check.KwargsNotSupportedException( actionName, kwargslist )

		_kwargs = dict()

		for kwarg in kwargs :

			matching = lib.str.mostlikely( kwarg, kwargslist )

			if not matching and spec.keywords :
				_kwargs[kwarg] = kwargs[kwarg]
			else :
				lib.check.KwargNameExists( kwarg, actionName, matching, kwargslist )
				lib.check.KwargNameNotAmbiguous( kwarg, actionName, matching )

				_kwargs[matching[0]] = kwargs[kwarg]

		kwargs = _kwargs

	# WE INFLATE AFTER RESOLVING KWARGS THUS
	# KWARGS IN JSON ARGS FILES MUST BE
	# EXACTLY MATCHING SPECS OF ACTIONS

	lib.args.inflate( args, kwargs )

	m = ( 0 if spec[0] is None else len( spec[0] ) ) -\
	    ( 0 if spec[3] is None else len( spec[3] ) )
	n = len( args )

	lib.check.NotTooFewArgumentsForAction( moduleName, actionName, n, m, spec )
	lib.check.NotTooManyArgumentsForAction( moduleName, actionName, n, m, spec )


	# DONE
	return args, kwargs


def wrapped ( argv ) :

	try :
		main( argv )

	except lib.error.MainException as e :
		print( e )


if __name__ == '__main__' :
	wrapped( sys.argv[1:] )
