# emacs-mode: -*- python-*-
from Plasma import *
from PlasmaTypes import *
import string
actTrigger = ptAttribActivator(1, 'Activator')
buttonID = ptAttribInt(2, 'Button id')
direction = ptAttribInt(3, 'Button direction')
pattern = ptAttribString(4, 'Responder name pattern FormString')
responders = ptAttribResponderList(5, 'Responderlist', byObject=1)
stringVarNames = ['CombinationLock0', 'CombinationLock1', 'CombinationLock2', 'CombinationLock3', 'CombinationLockDoor']
up_buttons = ['cLock_btn_d0_up','cLock_btn_d1_up','cLock_btn_d2_up','cLock_btn_d3_up','cLock_btn_d4_up']
down_buttons = ['cLock_btn_d0_down','cLock_btn_d1_down','cLock_btn_d2_down','cLock_btn_d3_down','cLock_btn_d4_down']
correctCombination = [4, 1, 6, 2]
secondaryCombination = [0, 7, 3, 8]
directions = ['UP', 'DOWN']
doorstates = ['CLOSED', 'OPEN']
AgeStartedIn = None

class relltooCombLockLogic(ptResponder):
    __module__ = __name__

    def __init__(self):
        ptResponder.__init__(self)
        self.id = 103350003
        self.version = 1


    def OnFirstUpdate(self):
        global AgeStartedIn
        AgeStartedIn = PtGetAgeName()


    def OnServerInitComplete(self):
        if (AgeStartedIn == PtGetAgeName()):
            ageSDL = PtGetAgeSDL()
            stringVarName = stringVarNames[buttonID.value]
            if (stringVarName != ''):
                ageSDL.setNotify(self.key, stringVarName, 0.0)
                ageSDL.setFlags(stringVarName, 1, 1)
                ageSDL.sendToClients(stringVarName)
                try:
                    CurrentValue = ageSDL[stringVarName][0]
                except:
                    PtDebugPrint('ERROR: relltooCombLockLogic.OnServerInitComplete():\tERROR reading age SDL')
                PtDebugPrint(('DEBUG: relltooCombLockLogic.OnServerInitComplete() for button %d %s' % (buttonID.value, directions[direction.value])))
                self.SetStoredCombination()     # Retrieve combination digit from savefile and set digit wheel anim states accordingly
                self.TestAndSuppressButtons()   # Disable up- or down buttons for any wheels that are in either end position       
            else:
                PtDebugPrint('ERROR: relltooCombLockLogic.OnServerInitComplete():\tERROR: missing SDL var name')
        

    def OnNotify(self, state, id, events):
        if ((not state) or (id != actTrigger.id)):
            return 
        if (not PtWasLocallyNotified(self.key)):
            return 
        elif ((type(actTrigger.value) == type([])) and (len(actTrigger.value) > 0)):
            PtDebugPrint(('DEBUG: relltooCombLockLogic.OnNotify()'))
            PtDebugPrint(('       Local player moved combination lock switch %d %s via %s' % (buttonID.value, directions[direction.value], actTrigger.value[0].getName())))
        stringVarName = stringVarNames[buttonID.value]
        if (stringVarName == ''):
            PtDebugPrint('ERROR: relltooCombLockLogic.OnNotify(): ERROR: missing SDL var name')
            return 
        if (AgeStartedIn == PtGetAgeName()):
            ageSDL = PtGetAgeSDL()
            tempint = ageSDL[stringVarNames[buttonID.value]][0]
            if (buttonID.value == 4):   # If buttonID specifies the door control, toggle open/closed state.
                if (direction.value):
                    PtDebugPrint(('\t\tattempting to open door.'))
                    ageSDL.setTagString(stringVarNames[4], 'try_open')  # Set to open, but flag that the combination
                    ageSDL.setIndex(stringVarNames[4], 0, true)         # is to be tested as a conditional to opening
                else:
                    PtDebugPrint(('\t\tlocal player closing door.'))
                    ageSDL.setTagString(stringVarNames[4], 'close')        # No conditions for closing
                    ageSDL.setIndex(stringVarNames[4], 0, false)
            else:       # If buttonID specifies one of the codewheels, adjust its value.
                if (direction.value):
                    if (tempint < 8):
                        tempint = tempint + 1
                        PtDebugPrint(('\t\tlocal player increments the value of digit wheel %d to %d.' % (buttonID.value, tempint)))
                else:
                    if (tempint > 0):
                        tempint = tempint - 1
                        PtDebugPrint(('\t\tlocal player decrements the value of digit wheel %d to %d.' % (buttonID.value, tempint)))
                ageSDL.setTagString(stringVarNames[buttonID.value], directions[direction.value])    # direction in tag
                ageSDL.setIndex(stringVarNames[buttonID.value], 0, tempint)


    def OnSDLNotify(self, VARname, SDLname, playerID, tag):
        if (AgeStartedIn == PtGetAgeName()):
            ageSDL = PtGetAgeSDL()
            VARmatchfoundflag = 0
            for stringVarName in stringVarNames:    # Check specified variable against recognised ones and print any match as debug info
                if (VARname == stringVarName): 
                    PtDebugPrint(('DEBUG: relltooCombLockLogic.OnSDLNotify():'))
                    PtDebugPrint(('       VARname:%s, SDLname:%s, tag:%s, value:%d' % (VARname, SDLname, tag, ageSDL[stringVarName][0])))
                    VARmatchfoundflag = 1
            if not (VARmatchfoundflag):
                PtDebugPrint(('ERROR: relltooCombLockLogic.OnSDLNotify() Specified VARname:%s not recognised by this script.' % (VARname)))
                return
            if playerID:
                objAvatar = ptSceneobject(PtGetAvatarKeyFromClientID(playerID), self.key)
            else:
                objAvatar = None
            PtDebugPrint(('       notification from playerID: %d' % playerID))
            if (VARname == 'CombinationLockDoor'):
                tempbool = ageSDL[VARname][0]   # 0=closed door,  1=open door
                if ((tag == 'try_open') and (direction.value == 1)):    # opening only on DOWN button's responders
                    print '\t\tDoor switch downwards, testing combination...',
                    if ((ageSDL['CombinationLock0'][0] == correctCombination[0]) and (ageSDL['CombinationLock1'][0] == correctCombination[1]) and (ageSDL['CombinationLock2'][0] == correctCombination[2]) and (ageSDL['CombinationLock3'][0] == correctCombination[3])):
                        print 'Combination correct, opening door.'
                        self.GoGoGadgetResponder(1, objAvatar, 0)   # Resp.1 = open door + switch goes down & stays down
                        print '\t\tTagging SDL variable as open'
                        ageSDL.setTagString(stringVarNames[4], 'open')    # Door is tagged as successfully opened
                        self.TestAndSuppressButtons()
                        print '\t\tSetting combination SDL vals to secondary combination.'
                        for index in range(4):
                            ageSDL.setTagString(stringVarNames[index], 'ignore')
                            ageSDL.setIndex(stringVarNames[index], 0, secondaryCombination[index])
                        return
                    else:
                        print 'Combination incorrect, cue sad trumpet.'
                        self.GoGoGadgetResponder(0, objAvatar, 0)   # Resp.0 = door remains closed + switch returns up after oneshot
                        print '\t\tResetting SDL variable to closed state.'
                        ageSDL.setTagString(stringVarNames[4], 'fail-open')   #  Door is tagged with shamefully unsuccessful opening attempt
                        ageSDL.setIndex(stringVarNames[4], 0, false)
                        return
                if ((tag == 'close') and (direction.value == 0)):   # closing only on UP button's responders
                    print '\t\tDoor switch upwards, closing door...'
                    self.GoGoGadgetResponder(0, objAvatar, 0)   # Resp.2 = close door + switch goes up & stays up
                    self.TestAndSuppressButtons()
                    return
            else:
                tempint = ageSDL[VARname][0]
                if (tag == directions[direction.value]):
                    print '\t\tTurning wheel', buttonID.value, tag
                    self.GoGoGadgetResponder(tempint, objAvatar, 0)   # Turn code wheel
                    self.TestAndSuppressButtons()


    def GoGoGadgetResponder(self, respie, avvie, ff):
        respondername = (pattern.value % (respie))
        for key in responders.byObject.keys():
            if (key == respondername):
                PtDebugPrint(('\t\tRunning responder %s on %s.' % (respondername, self.sceneobject.getName())))
                responders.run(self.key, avatar=avvie, objectName=respondername, fastforward=ff)
                break


    def SetStoredCombination(self):
        ageSDL = PtGetAgeSDL()
        tempint = ageSDL[stringVarNames[buttonID.value]][0]
        if (buttonID.value == 4):
            if ((direction.value == 0) and (tempint == 0)):
                self.GoGoGadgetResponder(0, None, 1)
            if ((direction.value == 1) and (tempint == 1)):
                self.GoGoGadgetResponder(1, None, 1)
        else:
            if (direction.value):                                         # Set values using DOWN BUTTON's responders
                self.GoGoGadgetResponder(tempint, None, 1)


    def TestAndSuppressButtons(self):
        ageSDL = PtGetAgeSDL()
        stringVarName = stringVarNames[buttonID.value]
        tempInt = ageSDL[stringVarName][0]
        if (buttonID.value == 4):
            print "\t\tDoor is", doorstates[tempInt],
        else:
            print "\t\tCode wheel", buttonID.value, "=", tempInt,
        print " Active buttons:",
        buttonObj = PtFindSceneobject(up_buttons[buttonID.value],AgeStartedIn)
        if (tempInt < 1):
            buttonObj.physics.suppress(true)
        else:
            buttonObj.physics.suppress(false)
            print "UP",
        buttonObj = PtFindSceneobject(down_buttons[buttonID.value],AgeStartedIn)            
        if (tempInt > 7) or ((buttonID.value == 4) and (tempInt)):  # Max.value is 7 for codewheel, or true for door state
            buttonObj.physics.suppress(true)
        else:
            buttonObj.physics.suppress(false)
            print "DOWN",
        print ''



### Python Glue ###

glue_cl = None
glue_inst = None
glue_params = None
glue_paramKeys = None
try:
    x = glue_verbose
except NameError:
    glue_verbose = 0

def glue_getClass():
    global glue_cl
    if (glue_cl == None):
        try:
            cl = eval(glue_name)
            if issubclass(cl, ptModifier):
                glue_cl = cl
            elif glue_verbose:
                print ('Class %s is not derived from modifier' % cl.__name__)
        except NameError:
            if glue_verbose:
                try:
                    print ('Could not find class %s' % glue_name)
                except NameError:
                    print 'Filename/classname not set!'
    return glue_cl


def glue_getInst():
    global glue_inst
    if (type(glue_inst) == type(None)):
        cl = glue_getClass()
        if (cl != None):
            glue_inst = cl()
    return glue_inst


def glue_delInst():
    global glue_inst
    global glue_cl
    global glue_paramKeys
    global glue_params
    if (type(glue_inst) != type(None)):
        del glue_inst
    glue_cl = None
    glue_params = None
    glue_paramKeys = None


def glue_getVersion():
    inst = glue_getInst()
    ver = inst.version
    glue_delInst()
    return ver


def glue_findAndAddAttribs(obj, glue_params):
    if isinstance(obj, ptAttribute):
        if glue_params.has_key(obj.id):
            if glue_verbose:
                print 'WARNING: Duplicate attribute ids!'
                print ('%s has id %d which is already defined in %s' %
                      (obj.name, obj.id, glue_params[obj.id].name))
        else:
            glue_params[obj.id] = obj
    elif type(obj) == type([]):
        for o in obj:
            glue_findAndAddAttribs(o, glue_params)
    elif type(obj) == type({}):
        for o in obj.values():
            glue_findAndAddAttribs(o, glue_params)
    elif type(obj) == type(()):
        for o in obj:
            glue_findAndAddAttribs(o, glue_params)


def glue_getParamDict():
    global glue_paramKeys
    global glue_params
    if type(glue_params) == type(None):
        glue_params = {}
        gd = globals()
        for obj in gd.values():
            glue_findAndAddAttribs(obj, glue_params)
        glue_paramKeys = glue_params.keys()
        glue_paramKeys.sort()
        glue_paramKeys.reverse()
    return glue_params


def glue_getClassName():
    cl = glue_getClass()
    if (cl != None):
        return cl.__name__
    if glue_verbose:
        print ('Class not found in %s.py' % glue_name)
    return None


def glue_getBlockID():
    inst = glue_getInst()
    if (inst != None):
        return inst.id
    if glue_verbose:
        print ('Instance could not be created in %s.py' % glue_name)
    return None


def glue_getNumParams():
    pd = glue_getParamDict()
    if (pd != None):
        return len(pd)
    if glue_verbose:
        print ('No attributes found in %s.py' % glue_name)
    return 0


def glue_getParam(number):
    pd = glue_getParamDict()
    if (pd != None):
        if type(glue_paramKeys) == type([]):
            if (number >= 0) and (number < len(glue_paramKeys)):
                return pd[glue_paramKeys[number]].getdef()
            else:
                print ('glue_getParam: Error! %d out of range of attribute list' % number)
        else:
            pl = pd.values()
            if (number >= 0) and (number < len(pl)):
                return pl[number].getdef()
            elif glue_verbose:
                print ('glue_getParam: Error! %d out of range of attribute list' % number)
    if glue_verbose:
        print 'GLUE: Attribute list error'
    return None


def glue_setParam(id, value):
    pd = glue_getParamDict()
    if (pd != None):
        if pd.has_key(id):
            try:
                pd[id].__setvalue__(value)
            except AttributeError:
                if isinstance(pd[id], ptAttributeList):
                    try:
                        if type(pd[id].value) != type([]):
                            pd[id].value = []
                    except AttributeError:
                        pd[id].value = []
                    pd[id].value.append(value)
                else:
                    pd[id].value = value
        elif glue_verbose:
            print "setParam: can't find id=", id
    else:
        print 'setParma: Something terribly has gone wrong. Head for the cover.'


def glue_isNamedAttribute(id):
    pd = glue_getParamDict()
    if (pd != None):
        try:
            if isinstance(pd[id], ptAttribNamedActivator):
                return 1
            if isinstance(pd[id], ptAttribNamedResponder):
                return 2
        except KeyError:
            if glue_verbose:
                print ('Could not find id=%d attribute' % id)
    return 0


def glue_isMultiModifier():
    inst = glue_getInst()
    if isinstance(inst, ptMultiModifier):
        return 1
    return 0


def glue_getVisInfo(number):
    pd = glue_getParamDict()
    if pd != None:
        if type(glue_paramKeys) == type([]):
            if (number >= 0) and (number < len(glue_paramKeys)):
                return pd[glue_paramKeys[number]].getVisInfo()
            else:
                print ('glue_getVisInfo: Error! %d out of range of attribute list' % number)
        else:
            pl = pd.values()
            if (number >= 0) and (number < len(pl)):
                return pl[number].getVisInfo()
            elif glue_verbose:
                print ('glue_getVisInfo: Error! %d out of range of attribute list' % number)
    if glue_verbose:
        print 'GLUE: Attribute list error'
    return None
