#
# $Id: cmdint.py,v 1.1.1.1 2003/03/22 05:15:49 dbelan2 Exp $
#
# Command Interpreter.
# Reads user commands from stdin in and execute
# them.
# 
# $Log: cmdint.py,v $
# Revision 1.1.1.1  2003/03/22 05:15:49  dbelan2
# Initial import of all public_html on www.cs.mcgill.ca.
#
# Revision 1.10  2001/10/01 16:27:19  hchen19
# no comment
#
# Revision 1.9  2001/09/30 19:25:44  hchen19
# A full functional version with good text interface and tolerance.
#
# Revision 1.8  2001/09/29 22:20:56  hchen19
# User can use command rather than method call.
#
# Revision 1.7  2001/09/29 16:33:31  hchen19
# some useless statement are omitted.
#
# Revision 1.6  2001/09/28 15:31:23  hchen19
# the system can save the simulation result to a specific file
#
# Revision 1.5  2001/09/26 20:32:46  dbelan2
# *** empty log message ***
#
# Revision 1.4  2001/09/25 16:54:45  dbelan2
# - Basic save state, load state implemented.
#
# Revision 1.3  2001/09/25 02:36:28  dbelan2
# - Implemented methods to specify output format and
#   output device (plot or file).  Can also specify
#   what variable (including time) to plot.
#
# Revision 1.2  2001/09/25 01:13:42  dbelan2
# - Improved code structure by making it more object
#   oriented.
# - Basic command interpreter running
# - Getting more general
#
# Revision 1.1  2001/09/21 15:25:15  dbelan2
# Basic cmd interpreter.
#
#
#
import sys
import string
from data import *
from  main import *
#from main import *
#from main import printModelInfo

#model = None

#import main

def infovar(block):
    str = block.name + "("
    if isinstance(block, Constant): # in case constant not evaluated
        str = str + `block.value`
    else:
        str = str + `block.output_value`
    str = str + ")"
    return str

class CmdInt:

    def __init__(self):
        #global model
        #model = model1
        self.model = None
        self.solver = None
        #self.solver = Solver()
	
	self.cmddictionary={
		'help':['Usage: help','--Purpose: show all the available commands'],
		'man':['Usage: man command','--Purpose: get usage and purpose of a command'],
		'go':['Usage: go', '--Purpose: start the simulator.'],
		'dependence':['Usage: dependence', '--Purpose: show the dependence information about the blocks of model.'],
		'loadmodel':['Usage: loadmodel modelfilename', '--Purpose: load a model from a file to the simulator.'],
		'setsimparam':['Usage: setsimparam param value','--Purpose: set simulator parameter includes comm_int, step_size, start_t, end_t.'],
		'showblocksinfo':['Usage: showblocksinfo','--Purpose: show the information about the blocks of model.'],
		'setconstval':['Usage:setconstval constblockname value','--Purpose: set constant block value.'],
		'savesimparam':['Usage:savesimparam', '--Purpose: save simulator parameters in a default file.'],
		'savestate':['Usage:savestate statefilename','--Purpose: save state of model into a file.'],
		'loadstate':['Usage:loadstate statefilename','--Purpose: load a state of model from a file.'],
		'outputblocks':['Usage:outputblocks blockname [blockname ...]','--Purpose: specify the block for output.'],
		'outputfname':['Usage:outputfname filename','--Purpose:specify the filename for store the simulator output.'],
		'saveoutput':['Usage:saveoutput', '--Purpose:ask simulator to store output to the specified filename.'],
		'quit':['Usage:quit','--Purpose:exit the simulator']}

    def help(self):
	print "---------available commands-----------------"
	for each in self.cmddictionary.keys():
		print each, self.cmddictionary[each][1]        

    def run(self):
	self.help()

        while 1:
            cmd = raw_input("> ")
 
            if cmd == "":
                continue

            cmdargs=string.split(cmd)
            argsnum=len(cmdargs)-1

		
	    if cmdargs[0]=='help':
		self.help()		
	    elif cmdargs[0]=='man':
		if self.cmddictionary.has_key(cmdargs[1]):
			print (self.cmddictionary[cmdargs[1]])[0]
			print (self.cmddictionary[cmdargs[1]])[1]
		else:
			print 'No such command'	
	    elif not self.cmddictionary.has_key(cmdargs[0]):
		print 'No such command'
            elif cmdargs[0]=='quit':
		if argsnum==0:
                	break
		else:
			print (self.cmddictionary[cmdargs[0]])[0]
	    elif cmdargs[0]=='loadmodel':
                if argsnum==1:
                    try:
                        self._user_loadmodel(cmdargs[1])
                    except IOError:
                        print 'Error: cannot open', cmdargs[1]
                else:
                    print (self.cmddictionary[cmdargs[0]])[0]

            elif cmdargs[0]=='loadstate':
                if argsnum==1:
                    try:
                        self._user_loadstate(cmdargs[1])
                    except IOError:
                        print 'Error: can not open', cmdargs[1]
                else:
                    print (self.cmddictionary[cmdargs[0]])[0]
	    else:
		if self.model==None:
			print 'No model is loaded'
            	elif cmdargs[0]=='go':
			if argsnum==0:
                		self._user_go()
			else:
				print (self.cmddictionary[cmdargs[0]])[0]
            	elif cmdargs[0]=='dependence':
			if argsnum==0:
                    		self._user_dependence()
			else:
				print (self.cmddictionary[cmdargs[0]])[0]
            	elif cmdargs[0]=='setsimparam':
                	if argsnum==2:
                    		if cmdargs[1]=='step_size' or cmdargs[1]=='comm_int' or  \
                       				cmdargs[1]=='start_t' or cmdargs[1]=='end_t':
                        		try:
                            			self._user_setsimparam(cmdargs[1], float(cmdargs[2]))
                        		except ValueError:
                            			print cmdargs[2], 'is not a digital value'
                    		else:
                        		print 'Error: you can only set one of the following settings:\
                        		step_size, comm_int, start_t, end_t'
                	else:
                    		print (self.cmddictionary[cmdargs[0]])[0]
            	elif cmdargs[0]=='showblocksinfo':
                	if argsnum==0:
                    		self._user_showblocksinfo()
                	else:
                    		print (self.cmddictionary[cmdargs[0]])[0]
            	elif cmdargs[0]=='setconstval':
                	if argsnum==2:
                    		self._user_setconstval(cmdargs[1], float(cmdargs[2]))
                	else:
                    		print (self.cmddictionary[cmdargs[0]])[0]
            	elif cmdargs[0]=='savesimparam':
                	if argsnum==0:
                    		self._user_savesimparam()
                	else:
                    		print (self.cmddictionary[cmdargs[0]])[0]
            	elif cmdargs[0]=='savestate':
                	if argsnum==1:
                    		self._user_savestate(cmdargs[1])
                	else:
                    		print (self.cmddictionary[cmdargs[0]])[0]
            	
            	elif cmdargs[0]=='outputblocks':
                	if argsnum>1:
                    		listargs=[]
                    		i=1
                    		while(i<=argsnum):
					if not (self.solver.blockInModelCheck(cmdargs[i]) or cmdargs[i]=='time'):
						blockinmodel=0
						break
					i=i+1
		    		if (i>argsnum):
					j=1
					while(j<=argsnum):
						listargs.append(cmdargs[j])
		  				j=j+1
                        		self._user_outputblocks(listargs)
		    		else:
					print 'Error: the block name '+`cmdargs[i]`+' is not in the system model'
                	else:
                    		print (self.cmddictionary[cmdargs[0]])[0]
            	elif cmdargs[0]=='outputfname':
                	if argsnum==1:
                    		self._user_outputfname(cmdargs[1])
                	else:
                    		print (self.cmddictionary[cmdargs[0]])[0]
	   
	    	elif cmdargs[0]=='saveoutput':
			if argsnum==0:
				self._user_saveoutput()
			else:
				print (self.cmddictionary[cmdargs[0]])[0]
            	else:
			pass

    # user commands

    def _user_go(self):
        self.solver.go()

    def _user_dependence(self):
        self.solver.printModelInfo()

    def _user_loadmodel(self, filename):
        execfile(filename)
        self.solver = Solver(self.model)

    def _user_setsimparam(self, var, value):
        # could check var if one of the valid 4 variable names
        exec('self.solver.' + var + ' = ' + `value`)

    def _user_showblocksinfo(self):
        #if varlist == None:
        vars = self.solver.getvars()
        print "Variables are:"
        print "Constants: ", map(infovar, vars[0])
        print "Integrators: ", map(infovar, vars[1])
        print "Others blocks: ", map(infovar, vars[2])

    def _user_setconstval(self, varname, value):
	if self.solver.blockInModelCheck(varname):
        	vars = self.solver.getvars()
        	allvars = vars[0][:]
        	
		i=0
		while i<len(allvars):
			if varname==allvars[i].name:
				break
			else:
				i=i+1
		
		if i< len(allvars):
			self.solver.changeBlockValue(varname, value)
		#allvars.extend(vars[1])
        	#allvars.extend(vars[2])
		
        	#if varname in allvars:
            	#	if isinstance(var, Constant):
                #		var.value=value
            	else:
                	print 'Error: you can only set the value of constants'
        else:
            print 'Error: there is no block in the model system'

#        for var in allvars:
#            if var.name == varname:
#                if isinstance(var, Constant):
#                    var.value = value
#                else:
#                    print 'Error: you can only set the value of constants.'
#            else:
#                print 'Error: there is no such block in the model system'
        
    def _user_savesimparam(self):
        self.solver.writeDefaults()

    # save experiment state
    def _user_savestate(self, filename):
        self.solver.saveState(filename)

    def _user_loadstate(self, filename):
        if self.solver == None:
            self.solver = Solver()
        self.solver.loadState(filename)


    # _time is a special name --> value of t
    # blocknames is a list
    def _user_outputblocks(self, blocknames):
        self.solver.setOutputFormat(blocknames)

    def _user_outputfname(self, filename):
        self.solver.resultfilename=filename
        

    def _user_saveoutput(self):
	self.solver.saveResultToFile()

    #def setGlobal(globalDefault):
    #    pass
    
    def setConstant(constant_or_ic_name):
        pass

    #def getValue(block_name):
    #    pass

    #def getConfig():
    #    pass
        #return solver_config



    #list()
    #print "Dependency Graph"
    #print graph
    #print "Simplified Dependency Graph"

    def list(self):
        print """
        Blocks
        ======
        Name          Type        Value      Inputs         Ouput
        """
        for block in self.model.blocks:
            print block.name, type(block), block.output_value,
            print "I:",
            for input in block.inputs:
                print input.name,
            for output in block.outputs:
                print output.name,
            print
        print "=========================================================="
        

if __name__ == '__main__':
    ci = CmdInt()
    ci.run()



