from command import *
import copy
from types import *

import sys,os
sys.path.insert(0,os.pardir)
from constant import *

class Invoker(Command):
    def __init__(self):
        self.cmdhistory=[]
        self.statehistory=[]
        self.present=-0.5
        self.last=-1

    def invoke(self, command):
        #
        # After one invocation, how should the invoke know that invocation is successfully
        # executed by the receiver. We know that each cell data have a Tree object to represent
        # the cell value. If a cell is updated successfully, then the Tree object will be
        # changed, even they represent the same value. So to judge whether a cell is changed by
        # the invocation, we simply compare the before and after references to Tree object.
        #
        # The another advantage to do so, the Tree object has a string representation. This string
        # representation can be kept for remembering the state. Keeping the state is important to
        # support the undo and redo operations.
        #
        if isinstance(command, SetCommand):
            beforetree=command.receiver.getDataTree(command.row, command.col)
##             print `beforetree`, 'is a tree'
            ans=command.execute()
##             print ans
##             print 'the command is executed'
##             print command.receiver.getState()
            if type(ans) is TupleType:
                errno, errstr=ans
                if errno==LEXICALERROR:
                    print 'Lexical Error'
                    print errstr
                elif errno==SYNTAXERROR:
                    print 'Syntax Erro'
                    print errstr
                elif errno==CYCLICDEPENDENCEERROR:
                    print 'cyclic dependence detected'
                    for s in errstr:
                        print s
                else:
                    pass
            else:
                pass
                #print ans

            aftertree=command.receiver.getDataTree(command.row, command.col)
            if beforetree!=aftertree:
                self.statehistory=self.statehistory[0:int(self.present)+1]

                precmd=copy.copy(command)
                precmd.setAssignment(`beforetree`)
                self.statehistory.append(HistoryNode(precmd, command))
                                
                self.present=self.present+1
                self.last=int(self.present)
        else:
            pass

    def undo(self):
        #print 'the value of self.present is: '+`self.present`
        if self.present<0:
            pass
        else:
            #print 'I did something'
            self.statehistory[int(self.present)].beforecmd.execute()
            self.present=self.present-1
            
    def redo(self):
        #print `self.last`, `self.present`, `self.floor(self.present)`

        #
        # if we use the ' int(self.present)<self.last' for the test. It will have some
        # bug in it. Since int(-0.5)=int(0.5).
        #
        if self.floor(self.present)<self.last:
            self.present=self.present+1
            self.statehistory[int(self.present)].aftercmd.execute()
        else:
            pass

    def floor(self, num):
        if num<0:
            return int(num)-1
        else:
            return int(num)

class HistoryNode:
    def __init__(self, beforecmd, aftercmd):
        self.beforecmd=beforecmd
        self.aftercmd=aftercmd
        





