class PChatInputSpeedChat(DirectObject.DirectObject):
    DefaultSCColorScheme = SCColorScheme(arrowColor=(1, 1, 1),
                                         rolloverColor=(1, 1, 1))

    def __init__(self):
        self.whisperId = None
        self.toPlayer = 0
        structure = []
        structure = scStructure
        self.createSpeedChatObject(structure)

        def listenForSCEvent(eventBaseName, handler, self=self):
            eventName = self.speedChat.getEventName(eventBaseName)
            self.accept(eventName, handler)

        listenForSCEvent(SpeedChatGlobals.SCStaticTextMsgEvent,
                         self.handleStaticTextMsg)
        listenForSCEvent(SpeedChatGlobals.SCGMTextMsgEvent,
                         self.handleGMTextMsg)
        listenForSCEvent(SpeedChatGlobals.SCCustomMsgEvent,
                         self.handleCustomMsg)
        listenForSCEvent(SpeedChatGlobals.SCEmoteMsgEvent, self.handleEmoteMsg)
        listenForSCEvent(SpeedChatGlobals.SCEmoteNoAccessEvent,
                         self.handleEmoteNoAccess)
        listenForSCEvent('SpeedChatStyleChange',
                         self.handleSpeedChatStyleChange)
        listenForSCEvent(PSpeedChatGlobals.PSpeedChatQuestMsgEvent,
                         self.handleQuestMsg)
        self.fsm = ClassicFSM.ClassicFSM('SpeedChat', [
            State.State('off', self.enterOff, self.exitOff, ['active']),
            State.State('active', self.enterActive, self.exitActive, ['off'])
        ], 'off', 'off')
        self.fsm.enterInitialState()
        self.mode = 'AllChat'
        self.whisperId = None
        self.gmHandler = None

    def reparentTo(self, newParent):
        self.baseFrame.reparentTo(newParent)

    def delete(self):
        self.ignoreAll()
        self.speedChat.destroy()
        del self.speedChat
        del self.fsm

    def setWhisperTo(self, whisperId, toPlayer=False):
        self.whisperId = whisperId
        self.toPlayer = toPlayer

    def show(self):
        self.speedChat.show()
        self.speedChat.setPos(Point3(0.11, 0, 0.92000000000000004))
        self.fsm.request('active')

    def hide(self):
        self.fsm.request('off')

    def enterOff(self):
        self.speedChat.hide()

    def exitOff(self):
        pass

    def requestMode(self, mode, whisperId=None):
        if mode == 'AllChat' and not base.talkAssistant.checkOpenSpeedChat():
            messenger.send('Chat-Failed open typed chat test')
            return None
        elif mode == 'PlayerWhisper':
            if not base.talkAssistant.checkWhisperSpeedChatPlayer(whisperId):
                messenger.send('Chat-Failed player typed chat test')
                return None

        elif mode == 'AvatarWhisper':
            if not base.talkAssistant.checkWhisperSpeedChatAvatar(whisperId):
                messenger.send('Chat-Failed avatar typed chat test')
                return None

        self.mode = mode
        self.whisperId = whisperId

    def enterActive(self):
        def handleCancel():
            localAvatar.chatMgr.speedChatDone(success=False)

        self.acceptOnce('mouse1', handleCancel)

        def selectionMade(self=self):
            localAvatar.chatMgr.speedChatDone()

        self.terminalSelectedEvent = self.speedChat.getEventName(
            SpeedChatGlobals.SCTerminalSelectedEvent)
        self.accept(self.terminalSelectedEvent, selectionMade)
        self.speedChat.reparentTo(base.a2dBottomLeft,
                                  DGG.FOREGROUND_SORT_INDEX)
        pos = self.speedChat.getPos()
        self.speedChat.setWhisperMode(self.whisperId != None)
        self.speedChat.enter()

    def exitActive(self):
        self.ignore('mouse1')
        self.ignore(self.terminalSelectedEvent)
        self.speedChat.exit()
        self.speedChat.detachNode()

    def handleLinkedEmote(self, emoteId):
        if self.whisperId is None:
            lt = base.localAvatar
            lt.b_setEmoteState(emoteId, animMultiplier=lt.animMultiplier)

    def sendChatByMode(self,
                       msgType,
                       textId,
                       questMsgType=0,
                       questInt=0,
                       taskNum=0,
                       questFlag=0):
        messenger.send('sentSpeedChat')
        if msgType == SPEEDCHAT_EMOTE:
            base.talkAssistant.sendOpenSpeedChat(msgType, textId)
            return None

        if msgType == GMCHAT:
            if self.gmHandler:
                base.talkAssistant.sendOpenTalk(
                    self.gmHandler.getPhrase(textId))

            return None

        if self.mode == 'PlayerWhisper':
            if questFlag:
                base.talkAssistant.sendPlayerWhisperQuestSpeedChat(
                    questInt, questMsgType, taskNum, self.whisperId)
            else:
                base.talkAssistant.sendPlayerWhisperSpeedChat(
                    msgType, textId, self.whisperId)
        elif self.mode == 'AvatarWhisper':
            if questFlag:
                base.talkAssistant.sendAvatarWhisperQuestSpeedChat(
                    questInt, questMsgType, taskNum, self.whisperId)
            else:
                base.talkAssistant.sendAvatarWhisperSpeedChat(
                    msgType, textId, self.whisperId)
        elif self.mode == 'GuildChat':
            if questFlag:
                base.talkAssistant.sendGuildSCQuestChat(
                    questMsgType, questInt, taskNum)
            else:
                base.talkAssistant.sendGuildSpeedChat(msgType, textId)
        elif self.mode == 'CrewChat':
            if questFlag:
                base.talkAssistant.sendPartySCQuestChat(
                    questMsgType, questInt, taskNum)
            else:
                base.talkAssistant.sendPartySpeedChat(msgType, textId)
        elif self.mode == 'ShipPVP':
            if questFlag:
                base.talkAssistant.sendShipPVPCrewSCQuestChat(
                    questInt, questMsgType, taskNum)
            else:
                base.talkAssistant.sendShipPVPCrewSpeedChat(msgType, textId)
        elif questFlag:
            base.talkAssistant.sendSCQuestChat(questMsgType, questInt, taskNum)
        else:
            base.talkAssistant.sendOpenSpeedChat(msgType, textId)

    def handleStaticTextMsg(self, textId):
        if textId in PLocalizer.EmoteMessagesSelf:
            self.handleEmoteMsg(textId)
        elif textId == EmoteGlobals.EMOTE_VALENTINES:
            self.handleEmoteMsg(textId)
        else:
            self.sendChatByMode(SPEEDCHAT_NORMAL, textId)
            self.hide()

    def handleGMTextMsg(self, textId):
        self.sendChatByMode(GMCHAT, textId)
        self.hide()

    def handleCustomMsg(self, textId):
        self.sendChatByMode(SPEEDCHAT_CUSTOM, textId)
        self.hide()

    def handleEmoteMsg(self, emoteId):
        sendText = True
        for prereq in EmoteGlobals.getEmotePrereqs(emoteId):
            if not prereq.avIsReady(localAvatar):
                return None
                continue

        if emoteId in OTPLocalizer.Emotes:
            sendText = localAvatar.requestEmote(emoteId)

        if sendText:
            if emoteId == EmoteGlobals.EMOTE_VALENTINES:
                emoteId = random.choice([
                    EmoteGlobals.EMOTE_VALENTINES_A,
                    EmoteGlobals.EMOTE_VALENTINES_B,
                    EmoteGlobals.EMOTE_VALENTINES_D,
                    EmoteGlobals.EMOTE_VALENTINES_E
                ])
                self.sendChatByMode(SPEEDCHAT_NORMAL, emoteId)
            else:
                self.sendChatByMode(SPEEDCHAT_EMOTE, emoteId)

        self.hide()

    def handleEmoteNoAccess(self):
        if self.whisperId is None:
            self.emoteNoAccessPanel.setPos(0, 0, 0)
        else:
            self.emoteNoAccessPanel.setPos(0.37, 0, 0)
        self.emoteNoAccessPanel.reparentTo(aspect2d)

    def handleEmoteNoAccessDone(self):
        self.emoteNoAccessPanel.detachNode()

    def handleQuestMsg(self, msgType, questInt, toNpcId, taskNum):
        self.sendChatByMode(None,
                            None,
                            questMsgType=msgType,
                            questInt=questInt,
                            taskNum=taskNum,
                            questFlag=1)
        self.hide()

    def handleSpeedChatStyleChange(self):
        (nameKey, arrowColor, rolloverColor, frameColor
         ) = speedChatStyles[base.localAvatar.getSpeedChatStyleIndex()]
        newSCColorScheme = SCColorScheme(arrowColor=arrowColor,
                                         rolloverColor=rolloverColor,
                                         frameColor=frameColor)
        self.speedChat.setColorScheme(newSCColorScheme)

    def createSpeedChatObject(self, structure):
        if hasattr(self, 'speedChat'):
            self.speedChat.exit()
            self.speedChat.destroy()
            del self.speedChat

        self.speedChat = SpeedChat(
            structure=structure,
            backgroundModelName='models/gui/SpeedChatPanel',
            guiModelName='models/textureCards/speedchatIcons')
        self.speedChat.setScale(0.040000000000000001)
        self.speedChat.setBin('gui-popup', 0)
        self.speedChat.setTopLevelOverlap(0.0)
        self.speedChat.setSubmenuOverlap(0.0)
        self.speedChat.setColorScheme(self.DefaultSCColorScheme)
        self.speedChat.finalizeAll()
        self.structure = structure

    def addGMSpeedChat(self):
        if not self.gmHandler:
            self.gmHandler = SpeedChatGMHandler.SpeedChatGMHandler()
            self.structure.insert(0, self.gmHandler.getStructure())
            self.speedChat.rebuildFromStructure(self.structure)

    def addFactoryMenu(self):
        fMenu = PSCFactoryMenu()
        fMenuHolder = SCMenuHolder(OTPLocalizer.SCMenuFactory, menu=fMenu)
        self.speedChat[2:2] = [fMenuHolder]

    def removeFactoryMenu(self):
        fMenu = self.speedChat[2]
        del self.speedChat[2]
        fMenu.destroy()

    def addCogMenu(self, indices):
        fMenu = PSCCogMenu(indices)
        fMenuHolder = SCMenuHolder(OTPLocalizer.SCMenuCog, menu=fMenu)
        self.speedChat[2:2] = [fMenuHolder]

    def removeCogMenu(self):
        fMenu = self.speedChat[2]
        del self.speedChat[2]
        fMenu.destroy()
class PChatInputEmote(DirectObject.DirectObject):
    DefaultSCColorScheme = SCColorScheme(arrowColor = (1, 1, 1), rolloverColor = (1, 1, 1))
    
    def __init__(self):
        self.whisperId = None
        self.toPlayer = 0
        structure = []
        structure.append([
            SCEmoteMenu,
            OTPLocalizer.SCMenuEmotions])
        self.emoteMenuIdx = len(structure) - 1
        structure.append([
            SCCustomMenu,
            OTPLocalizer.SCMenuCustom])
        structure += scStructure
        if base.config.GetInt('want-emotes', 1):
            emote_structure = None
            emote_dance_structure = None
            emote_general_structure = None
            emote_music_structure = None
            emote_expressions_structure = None
            avatar_gender = base.emoteGender
            idList = EmoteGlobals.emotes.keys()
            idList.sort()
            for id in idList:
                emote = EmoteGlobals.emotes.get(id)
                emote_group = EmoteGlobals.getEmoteGroup(id)
                emote_gender = EmoteGlobals.getEmoteGender(id)
                if id in [
                    EmoteGlobals.EMOTE_VALENTINES,
                    EmoteGlobals.EMOTE_NOISEMAKER,
                    EmoteGlobals.EMOTE_HALLOWEEN,
                    EmoteGlobals.EMOTE_COIN_TAILS]:
                    continue
                
                if not emote_structure:
                    emote_structure = [
                        OTPLocalizer.Emotes_Root]
                
                if not emote_dance_structure:
                    emote_dance_structure = [
                        OTPLocalizer.Emotes_Dances]
                    structure.append(emote_dance_structure)
                
                if not emote_general_structure:
                    emote_general_structure = [
                        OTPLocalizer.Emotes_General]
                    structure.append(emote_general_structure)
                
                if not emote_music_structure:
                    emote_music_structure = [
                        OTPLocalizer.Emotes_Music]
                    structure.append(emote_music_structure)
                
                if not emote_expressions_structure:
                    emote_expressions_structure = [
                        OTPLocalizer.Emotes_Expressions]
                    structure.append(emote_expressions_structure)
                
                if emote_gender == avatar_gender or emote_gender is None:
                    if emote_group == OTPLocalizer.Emotes_Dances:
                        emote_dance_structure.append(id)
                    elif emote_group == OTPLocalizer.Emotes_General:
                        structure.append(id)
                    elif emote_group == OTPLocalizer.Emotes_Music:
                        emote_music_structure.append(id)
                    elif emote_group == OTPLocalizer.Emotes_Expressions:
                        emote_expressions_structure.append(id)
                    
                emote_group == OTPLocalizer.Emotes_Dances
            
            if emote_structure:
                structure.insert(0, emote_structure)
            
        
        self.createSpeedChatObject(structure)
        
        def listenForSCEvent(eventBaseName, handler, self = self):
            eventName = self.speedChat.getEventName(eventBaseName)
            self.accept(eventName, handler)

        listenForSCEvent(SpeedChatGlobals.SCTerminalLinkedEmoteEvent, self.handleLinkedEmote)
        self.fsm = ClassicFSM.ClassicFSM('SpeedChat', [
            State.State('off', self.enterOff, self.exitOff, [
                'active']),
            State.State('active', self.enterActive, self.exitActive, [
                'off'])], 'off', 'off')
        self.fsm.enterInitialState()
        self.mode = 'AllChat'
        self.whisperId = None

    
    def updateEmoteList(self):
        idList = EmoteGlobals.emotes.keys()
        idList.sort()
        for emoteId in idList:
            if EmoteGlobals.getEmotePrereqs(emoteId):
                for prereq in EmoteGlobals.getEmotePrereqs(emoteId):
                    if not prereq.avIsReady(localAvatar) and emoteId in self.structure:
                        self.removeEmote(emoteId)
                        continue
                    if prereq.avIsReady(localAvatar) and emoteId not in self.structure:
                        self.addEmote(emoteId)
                        continue
                
        
        self.createSpeedChatObject(self.structure)

    
    def reparentTo(self, newParent):
        self.baseFrame.reparentTo(newParent)

    
    def delete(self):
        self.ignoreAll()
        self.speedChat.destroy()
        del self.speedChat
        del self.fsm

    
    def setWhisperTo(self, whisperId, toPlayer = False):
        self.whisperId = whisperId
        self.toPlayer = toPlayer

    
    def show(self):
        self.speedChat.show()
        bounds = self.speedChat.getTightBounds()
        zSize = bounds[1][2] - bounds[0][2]
        self.speedChat.setPos(Point3(0.025000000000000001, 0, zSize + 0.070000000000000007))
        self.fsm.request('active')

    
    def hide(self):
        self.fsm.request('off')

    
    def enterOff(self):
        self.speedChat.hide()

    
    def exitOff(self):
        pass

    
    def requestMode(self, mode, whisperId = None):
        if mode == 'AllChat' and not base.talkAssistant.checkOpenSpeedChat():
            messenger.send('Chat-Failed open typed chat test')
            return None
        elif mode == 'PlayerWhisper':
            if not base.talkAssistant.checkWhisperSpeedChatPlayer(whisperId):
                messenger.send('Chat-Failed player typed chat test')
                return None
            
        elif mode == 'AvatarWhisper':
            if not base.talkAssistant.checkWhisperSpeedChatAvatar(whisperId):
                messenger.send('Chat-Failed avatar typed chat test')
                return None
            
        
        self.mode = mode
        self.whisperId = whisperId

    
    def enterActive(self):
        
        def handleCancel():
            localAvatar.chatMgr.speedChatDone(success = False)

        self.acceptOnce('mouse1', handleCancel)
        
        def selectionMade(self = self):
            localAvatar.chatMgr.speedChatDone()

        self.terminalSelectedEvent = self.speedChat.getEventName(SpeedChatGlobals.SCTerminalSelectedEvent)
        self.accept(self.terminalSelectedEvent, selectionMade)
        self.speedChat.reparentTo(base.a2dBottomLeft, DGG.FOREGROUND_SORT_INDEX)
        pos = self.speedChat.getPos()
        self.speedChat.setWhisperMode(self.whisperId != None)
        self.speedChat.enter()

    
    def exitActive(self):
        self.ignore('mouse1')
        self.ignore(self.terminalSelectedEvent)
        self.speedChat.exit()
        self.speedChat.detachNode()

    
    def handleLinkedEmote(self, emoteId):
        if self.whisperId is None:
            lt = base.localAvatar
            lt.b_setEmoteState(emoteId, animMultiplier = lt.animMultiplier)
        

    
    def sendChatByMode(self, msgType, textId, questInt = 0, taskNum = 0, questFlag = 0):
        messenger.send('sentSpeedChat')
        if msgType == SPEEDCHAT_EMOTE:
            base.talkAssistant.sendOpenSpeedChat(msgType, textId)
            return None
        
        if msgType == GMCHAT:
            gmHandler = SpeedChatGMHandler.SpeedChatGMHandler()
            base.talkAssistant.sendOpenTalk(gmHandler.getPhrase(textId))
            return None
        
        if self.mode == 'PlayerWhisper':
            if questFlag:
                base.talkAssistant.sendPlayerWhisperQuestSpeedChat(questInt, msgType, taskNum, self.whisperId)
            else:
                base.talkAssistant.sendPlayerWhisperSpeedChat(msgType, textId, self.whisperId)
        elif self.mode == 'AvatarWhisper':
            if questFlag:
                pass
            else:
                base.talkAssistant.sendAvatarWhisperSpeedChat(msgType, textId, self.whisperId)
        elif self.mode == 'GuildChat':
            if questFlag:
                base.talkAssistant.sendGuildSCQuestChat(msgType, questInt, taskNum)
            else:
                base.talkAssistant.sendGuildSpeedChat(msgType, textId)
        elif self.mode == 'CrewChat':
            if questFlag:
                base.talkAssistant.sendPartySCQuestChat(msgType, questInt, taskNum)
            else:
                base.talkAssistant.sendPartySpeedChat(msgType, textId)
        elif self.mode == 'ShipPVP':
            if questFlag:
                base.talkAssistant.sendShipPVPCrewSCQuestChat(questInt, msgType, taskNum)
            else:
                base.talkAssistant.sendShipPVPCrewSpeedChat(msgType, textId)
        elif questFlag:
            base.talkAssistant.sendSCQuestChat(msgType, questInt, taskNum)
        else:
            base.talkAssistant.sendOpenSpeedChat(msgType, textId)

    
    def handleStaticTextMsg(self, textId):
        if textId in PLocalizer.EmoteMessagesSelf:
            self.handleEmoteMsg(textId)
        elif textId == EmoteGlobals.EMOTE_VALENTINES:
            self.handleEmoteMsg(textId)
        else:
            self.sendChatByMode(SPEEDCHAT_NORMAL, textId)
            self.hide()

    
    def handleGMTextMsg(self, textId):
        self.sendChatByMode(GMCHAT, textId)
        self.hide()

    
    def handleCustomMsg(self, textId):
        self.sendChatByMode(3, textId)
        self.hide()

    
    def handleEmoteMsg(self, emoteId):
        sendText = True
        for prereq in EmoteGlobals.getEmotePrereqs(emoteId):
            if not prereq.avIsReady(localAvatar):
                return None
                continue
        
        if emoteId in OTPLocalizer.Emotes:
            sendText = localAvatar.requestEmote(emoteId)
        
        if sendText:
            if emoteId == EmoteGlobals.EMOTE_VALENTINES:
                emoteId = random.choice([
                    EmoteGlobals.EMOTE_VALENTINES_A,
                    EmoteGlobals.EMOTE_VALENTINES_B,
                    EmoteGlobals.EMOTE_VALENTINES_D,
                    EmoteGlobals.EMOTE_VALENTINES_E])
                self.sendChatByMode(1, emoteId)
            else:
                self.sendChatByMode(2, emoteId)
        
        self.hide()

    
    def handleQuestMsg(self, questInt, toNpcId, msgType, taskNum):
        self.sendChatByMode(msgType, '', questInt, taskNum, 1)
        self.hide()

    
    def handleSpeedChatStyleChange(self):
        (nameKey, arrowColor, rolloverColor, frameColor) = speedChatStyles[base.localAvatar.getSpeedChatStyleIndex()]
        newSCColorScheme = SCColorScheme(arrowColor = arrowColor, rolloverColor = rolloverColor, frameColor = frameColor)
        self.speedChat.setColorScheme(newSCColorScheme)

    
    def createSpeedChatObject(self, structure):
        if hasattr(self, 'speedChat'):
            self.speedChat.exit()
            self.speedChat.destroy()
            del self.speedChat
        
        self.speedChat = SpeedChat(structure = structure, backgroundModelName = 'models/gui/SpeedChatPanel', guiModelName = 'models/textureCards/speedchatIcons')
        self.speedChat.setScale(0.040000000000000001)
        self.speedChat.setBin('gui-popup', 0)
        self.speedChat.setTopLevelOverlap(0.0)
        self.speedChat.setSubmenuOverlap(0.0)
        self.speedChat.setColorScheme(self.DefaultSCColorScheme)
        self.speedChat.finalizeAll()
        self.structure = structure

    
    def addGMSpeedChat(self):
        gmHandler = SpeedChatGMHandler.SpeedChatGMHandler()
        self.structure.insert(0, gmHandler.getStructure())
        self.speedChat.rebuildFromStructure(self.structure)

    
    def addFactoryMenu(self):
        fMenu = PSCFactoryMenu()
        fMenuHolder = SCMenuHolder(OTPLocalizer.SCMenuFactory, menu = fMenu)
        self.speedChat[2:2] = [
            fMenuHolder]

    
    def removeFactoryMenu(self):
        fMenu = self.speedChat[2]
        del self.speedChat[2]
        fMenu.destroy()

    
    def addCogMenu(self, indices):
        fMenu = PSCCogMenu(indices)
        fMenuHolder = SCMenuHolder(OTPLocalizer.SCMenuCog, menu = fMenu)
        self.speedChat[2:2] = [
            fMenuHolder]

    
    def removeCogMenu(self):
        fMenu = self.speedChat[2]
        del self.speedChat[2]
        fMenu.destroy()

    
    def addEmote(self, emoteId):
        emote = EmoteGlobals.emotes.get(emoteId)
        emote_group = EmoteGlobals.getEmoteGroup(emoteId)
        if emote is None:
            return None
        
        if emoteId not in self.structure:
            self.structure.append(emoteId)
        
        self.createSpeedChatObject(self.structure)

    
    def removeEmote(self, emoteId):
        emote = EmoteGlobals.emotes.get(emoteId)
        emote_group = EmoteGlobals.getEmoteGroup(emoteId)
        if emote is None:
            return None
        
        if emoteId in self.structure:
            self.structure.remove(emoteId)
        
        self.createSpeedChatObject(self.structure)
class PChatInputEmote(DirectObject.DirectObject):
    DefaultSCColorScheme = SCColorScheme(
        arrowColor=(1, 1, 1), rolloverColor=(1, 1, 1))

    def __init__(self):
        self.whisperId = None
        self.toPlayer = 0
        structure = []
        structure.append([SCEmoteMenu, OTPLocalizer.SCMenuEmotions])
        self.emoteMenuIdx = len(structure) - 1
        structure.append([SCCustomMenu, OTPLocalizer.SCMenuCustom])
        structure += scStructure
        if base.config.GetInt('want-emotes', 1):
            emote_structure = None
            emote_dance_structure = None
            emote_general_structure = None
            emote_music_structure = None
            emote_expressions_structure = None
            avatar_gender = base.emoteGender
            idList = EmoteGlobals.emotes.keys()
            idList.sort()
            for id in idList:
                emote = EmoteGlobals.emotes.get(id)
                emote_group = EmoteGlobals.getEmoteGroup(id)
                emote_gender = EmoteGlobals.getEmoteGender(id)
                if id in [
                        EmoteGlobals.EMOTE_VALENTINES,
                        EmoteGlobals.EMOTE_NOISEMAKER,
                        EmoteGlobals.EMOTE_HALLOWEEN,
                        EmoteGlobals.EMOTE_COIN_TAILS
                ]:
                    continue

                if not emote_structure:
                    emote_structure = [OTPLocalizer.Emotes_Root]

                if not emote_dance_structure:
                    emote_dance_structure = [OTPLocalizer.Emotes_Dances]
                    structure.append(emote_dance_structure)

                if not emote_general_structure:
                    emote_general_structure = [OTPLocalizer.Emotes_General]
                    structure.append(emote_general_structure)

                if not emote_music_structure:
                    emote_music_structure = [OTPLocalizer.Emotes_Music]
                    structure.append(emote_music_structure)

                if not emote_expressions_structure:
                    emote_expressions_structure = [
                        OTPLocalizer.Emotes_Expressions
                    ]
                    structure.append(emote_expressions_structure)

                if emote_gender == avatar_gender or emote_gender is None:
                    if emote_group == OTPLocalizer.Emotes_Dances:
                        emote_dance_structure.append(id)
                    elif emote_group == OTPLocalizer.Emotes_General:
                        structure.append(id)
                    elif emote_group == OTPLocalizer.Emotes_Music:
                        emote_music_structure.append(id)
                    elif emote_group == OTPLocalizer.Emotes_Expressions:
                        emote_expressions_structure.append(id)

                emote_group == OTPLocalizer.Emotes_Dances

            if emote_structure:
                structure.insert(0, emote_structure)

        self.createSpeedChatObject(structure)

        def listenForSCEvent(eventBaseName, handler, self=self):
            eventName = self.speedChat.getEventName(eventBaseName)
            self.accept(eventName, handler)

        listenForSCEvent(SpeedChatGlobals.SCTerminalLinkedEmoteEvent,
                         self.handleLinkedEmote)
        self.fsm = ClassicFSM.ClassicFSM('SpeedChat', [
            State.State('off', self.enterOff, self.exitOff, ['active']),
            State.State('active', self.enterActive, self.exitActive, ['off'])
        ], 'off', 'off')
        self.fsm.enterInitialState()
        self.mode = 'AllChat'
        self.whisperId = None

    def updateEmoteList(self):
        idList = EmoteGlobals.emotes.keys()
        idList.sort()
        for emoteId in idList:
            if EmoteGlobals.getEmotePrereqs(emoteId):
                for prereq in EmoteGlobals.getEmotePrereqs(emoteId):
                    if not prereq.avIsReady(
                            localAvatar) and emoteId in self.structure:
                        self.removeEmote(emoteId)
                        continue
                    if prereq.avIsReady(
                            localAvatar) and emoteId not in self.structure:
                        self.addEmote(emoteId)
                        continue

        self.createSpeedChatObject(self.structure)

    def reparentTo(self, newParent):
        self.baseFrame.reparentTo(newParent)

    def delete(self):
        self.ignoreAll()
        self.speedChat.destroy()
        del self.speedChat
        del self.fsm

    def setWhisperTo(self, whisperId, toPlayer=False):
        self.whisperId = whisperId
        self.toPlayer = toPlayer

    def show(self):
        self.speedChat.show()
        bounds = self.speedChat.getTightBounds()
        zSize = bounds[1][2] - bounds[0][2]
        self.speedChat.setPos(
            Point3(0.025000000000000001, 0, zSize + 0.070000000000000007))
        self.fsm.request('active')

    def hide(self):
        self.fsm.request('off')

    def enterOff(self):
        self.speedChat.hide()

    def exitOff(self):
        pass

    def requestMode(self, mode, whisperId=None):
        if mode == 'AllChat' and not base.talkAssistant.checkOpenSpeedChat():
            messenger.send('Chat-Failed open typed chat test')
            return None
        elif mode == 'PlayerWhisper':
            if not base.talkAssistant.checkWhisperSpeedChatPlayer(whisperId):
                messenger.send('Chat-Failed player typed chat test')
                return None

        elif mode == 'AvatarWhisper':
            if not base.talkAssistant.checkWhisperSpeedChatAvatar(whisperId):
                messenger.send('Chat-Failed avatar typed chat test')
                return None

        self.mode = mode
        self.whisperId = whisperId

    def enterActive(self):
        def handleCancel():
            localAvatar.chatMgr.speedChatDone(success=False)

        self.acceptOnce('mouse1', handleCancel)

        def selectionMade(self=self):
            localAvatar.chatMgr.speedChatDone()

        self.terminalSelectedEvent = self.speedChat.getEventName(
            SpeedChatGlobals.SCTerminalSelectedEvent)
        self.accept(self.terminalSelectedEvent, selectionMade)
        self.speedChat.reparentTo(base.a2dBottomLeft,
                                  DGG.FOREGROUND_SORT_INDEX)
        pos = self.speedChat.getPos()
        self.speedChat.setWhisperMode(self.whisperId != None)
        self.speedChat.enter()

    def exitActive(self):
        self.ignore('mouse1')
        self.ignore(self.terminalSelectedEvent)
        self.speedChat.exit()
        self.speedChat.detachNode()

    def handleLinkedEmote(self, emoteId):
        if self.whisperId is None:
            lt = base.localAvatar
            lt.b_setEmoteState(emoteId, animMultiplier=lt.animMultiplier)

    def sendChatByMode(self,
                       msgType,
                       textId,
                       questInt=0,
                       taskNum=0,
                       questFlag=0):
        messenger.send('sentSpeedChat')
        if msgType == SPEEDCHAT_EMOTE:
            base.talkAssistant.sendOpenSpeedChat(msgType, textId)
            return None

        if msgType == GMCHAT:
            gmHandler = SpeedChatGMHandler.SpeedChatGMHandler()
            base.talkAssistant.sendOpenTalk(gmHandler.getPhrase(textId))
            return None

        if self.mode == 'PlayerWhisper':
            if questFlag:
                base.talkAssistant.sendPlayerWhisperQuestSpeedChat(
                    questInt, msgType, taskNum, self.whisperId)
            else:
                base.talkAssistant.sendPlayerWhisperSpeedChat(
                    msgType, textId, self.whisperId)
        elif self.mode == 'AvatarWhisper':
            if questFlag:
                pass
            else:
                base.talkAssistant.sendAvatarWhisperSpeedChat(
                    msgType, textId, self.whisperId)
        elif self.mode == 'GuildChat':
            if questFlag:
                base.talkAssistant.sendGuildSCQuestChat(
                    msgType, questInt, taskNum)
            else:
                base.talkAssistant.sendGuildSpeedChat(msgType, textId)
        elif self.mode == 'CrewChat':
            if questFlag:
                base.talkAssistant.sendPartySCQuestChat(
                    msgType, questInt, taskNum)
            else:
                base.talkAssistant.sendPartySpeedChat(msgType, textId)
        elif self.mode == 'ShipPVP':
            if questFlag:
                base.talkAssistant.sendShipPVPCrewSCQuestChat(
                    questInt, msgType, taskNum)
            else:
                base.talkAssistant.sendShipPVPCrewSpeedChat(msgType, textId)
        elif questFlag:
            base.talkAssistant.sendSCQuestChat(msgType, questInt, taskNum)
        else:
            base.talkAssistant.sendOpenSpeedChat(msgType, textId)

    def handleStaticTextMsg(self, textId):
        if textId in PLocalizer.EmoteMessagesSelf:
            self.handleEmoteMsg(textId)
        elif textId == EmoteGlobals.EMOTE_VALENTINES:
            self.handleEmoteMsg(textId)
        else:
            self.sendChatByMode(SPEEDCHAT_NORMAL, textId)
            self.hide()

    def handleGMTextMsg(self, textId):
        self.sendChatByMode(GMCHAT, textId)
        self.hide()

    def handleCustomMsg(self, textId):
        self.sendChatByMode(3, textId)
        self.hide()

    def handleEmoteMsg(self, emoteId):
        sendText = True
        for prereq in EmoteGlobals.getEmotePrereqs(emoteId):
            if not prereq.avIsReady(localAvatar):
                return None
                continue

        if emoteId in OTPLocalizer.Emotes:
            sendText = localAvatar.requestEmote(emoteId)

        if sendText:
            if emoteId == EmoteGlobals.EMOTE_VALENTINES:
                emoteId = random.choice([
                    EmoteGlobals.EMOTE_VALENTINES_A,
                    EmoteGlobals.EMOTE_VALENTINES_B,
                    EmoteGlobals.EMOTE_VALENTINES_D,
                    EmoteGlobals.EMOTE_VALENTINES_E
                ])
                self.sendChatByMode(1, emoteId)
            else:
                self.sendChatByMode(2, emoteId)

        self.hide()

    def handleQuestMsg(self, questInt, toNpcId, msgType, taskNum):
        self.sendChatByMode(msgType, '', questInt, taskNum, 1)
        self.hide()

    def handleSpeedChatStyleChange(self):
        (nameKey, arrowColor, rolloverColor, frameColor
         ) = speedChatStyles[base.localAvatar.getSpeedChatStyleIndex()]
        newSCColorScheme = SCColorScheme(
            arrowColor=arrowColor,
            rolloverColor=rolloverColor,
            frameColor=frameColor)
        self.speedChat.setColorScheme(newSCColorScheme)

    def createSpeedChatObject(self, structure):
        if hasattr(self, 'speedChat'):
            self.speedChat.exit()
            self.speedChat.destroy()
            del self.speedChat

        self.speedChat = SpeedChat(
            structure=structure,
            backgroundModelName='models/gui/SpeedChatPanel',
            guiModelName='models/textureCards/speedchatIcons')
        self.speedChat.setScale(0.040000000000000001)
        self.speedChat.setBin('gui-popup', 0)
        self.speedChat.setTopLevelOverlap(0.0)
        self.speedChat.setSubmenuOverlap(0.0)
        self.speedChat.setColorScheme(self.DefaultSCColorScheme)
        self.speedChat.finalizeAll()
        self.structure = structure

    def addGMSpeedChat(self):
        gmHandler = SpeedChatGMHandler.SpeedChatGMHandler()
        self.structure.insert(0, gmHandler.getStructure())
        self.speedChat.rebuildFromStructure(self.structure)

    def addFactoryMenu(self):
        fMenu = PSCFactoryMenu()
        fMenuHolder = SCMenuHolder(OTPLocalizer.SCMenuFactory, menu=fMenu)
        self.speedChat[2:2] = [fMenuHolder]

    def removeFactoryMenu(self):
        fMenu = self.speedChat[2]
        del self.speedChat[2]
        fMenu.destroy()

    def addCogMenu(self, indices):
        fMenu = PSCCogMenu(indices)
        fMenuHolder = SCMenuHolder(OTPLocalizer.SCMenuCog, menu=fMenu)
        self.speedChat[2:2] = [fMenuHolder]

    def removeCogMenu(self):
        fMenu = self.speedChat[2]
        del self.speedChat[2]
        fMenu.destroy()

    def addEmote(self, emoteId):
        emote = EmoteGlobals.emotes.get(emoteId)
        emote_group = EmoteGlobals.getEmoteGroup(emoteId)
        if emote is None:
            return None

        if emoteId not in self.structure:
            self.structure.append(emoteId)

        self.createSpeedChatObject(self.structure)

    def removeEmote(self, emoteId):
        emote = EmoteGlobals.emotes.get(emoteId)
        emote_group = EmoteGlobals.getEmoteGroup(emoteId)
        if emote is None:
            return None

        if emoteId in self.structure:
            self.structure.remove(emoteId)

        self.createSpeedChatObject(self.structure)
class PChatInputSpeedChat(DirectObject.DirectObject):
    DefaultSCColorScheme = SCColorScheme(arrowColor = (1, 1, 1), rolloverColor = (1, 1, 1))
    
    def __init__(self):
        self.whisperId = None
        self.toPlayer = 0
        structure = []
        structure = scStructure
        self.createSpeedChatObject(structure)
        
        def listenForSCEvent(eventBaseName, handler, self = self):
            eventName = self.speedChat.getEventName(eventBaseName)
            self.accept(eventName, handler)

        listenForSCEvent(SpeedChatGlobals.SCStaticTextMsgEvent, self.handleStaticTextMsg)
        listenForSCEvent(SpeedChatGlobals.SCGMTextMsgEvent, self.handleGMTextMsg)
        listenForSCEvent(SpeedChatGlobals.SCCustomMsgEvent, self.handleCustomMsg)
        listenForSCEvent(SpeedChatGlobals.SCEmoteMsgEvent, self.handleEmoteMsg)
        listenForSCEvent(SpeedChatGlobals.SCEmoteNoAccessEvent, self.handleEmoteNoAccess)
        listenForSCEvent('SpeedChatStyleChange', self.handleSpeedChatStyleChange)
        listenForSCEvent(PSpeedChatGlobals.PSpeedChatQuestMsgEvent, self.handleQuestMsg)
        self.fsm = ClassicFSM.ClassicFSM('SpeedChat', [
            State.State('off', self.enterOff, self.exitOff, [
                'active']),
            State.State('active', self.enterActive, self.exitActive, [
                'off'])], 'off', 'off')
        self.fsm.enterInitialState()
        self.mode = 'AllChat'
        self.whisperId = None
        self.gmHandler = None

    
    def reparentTo(self, newParent):
        self.baseFrame.reparentTo(newParent)

    
    def delete(self):
        self.ignoreAll()
        self.speedChat.destroy()
        del self.speedChat
        del self.fsm

    
    def setWhisperTo(self, whisperId, toPlayer = False):
        self.whisperId = whisperId
        self.toPlayer = toPlayer

    
    def show(self):
        self.speedChat.show()
        self.speedChat.setPos(Point3(0.11, 0, 0.92000000000000004))
        self.fsm.request('active')

    
    def hide(self):
        self.fsm.request('off')

    
    def enterOff(self):
        self.speedChat.hide()

    
    def exitOff(self):
        pass

    
    def requestMode(self, mode, whisperId = None):
        if mode == 'AllChat' and not base.talkAssistant.checkOpenSpeedChat():
            messenger.send('Chat-Failed open typed chat test')
            return None
        elif mode == 'PlayerWhisper':
            if not base.talkAssistant.checkWhisperSpeedChatPlayer(whisperId):
                messenger.send('Chat-Failed player typed chat test')
                return None
            
        elif mode == 'AvatarWhisper':
            if not base.talkAssistant.checkWhisperSpeedChatAvatar(whisperId):
                messenger.send('Chat-Failed avatar typed chat test')
                return None
            
        
        self.mode = mode
        self.whisperId = whisperId

    
    def enterActive(self):
        
        def handleCancel():
            localAvatar.chatMgr.speedChatDone(success = False)

        self.acceptOnce('mouse1', handleCancel)
        
        def selectionMade(self = self):
            localAvatar.chatMgr.speedChatDone()

        self.terminalSelectedEvent = self.speedChat.getEventName(SpeedChatGlobals.SCTerminalSelectedEvent)
        self.accept(self.terminalSelectedEvent, selectionMade)
        self.speedChat.reparentTo(base.a2dBottomLeft, DGG.FOREGROUND_SORT_INDEX)
        pos = self.speedChat.getPos()
        self.speedChat.setWhisperMode(self.whisperId != None)
        self.speedChat.enter()

    
    def exitActive(self):
        self.ignore('mouse1')
        self.ignore(self.terminalSelectedEvent)
        self.speedChat.exit()
        self.speedChat.detachNode()

    
    def handleLinkedEmote(self, emoteId):
        if self.whisperId is None:
            lt = base.localAvatar
            lt.b_setEmoteState(emoteId, animMultiplier = lt.animMultiplier)
        

    
    def sendChatByMode(self, msgType, textId, questMsgType = 0, questInt = 0, taskNum = 0, questFlag = 0):
        messenger.send('sentSpeedChat')
        if msgType == SPEEDCHAT_EMOTE:
            base.talkAssistant.sendOpenSpeedChat(msgType, textId)
            return None
        
        if msgType == GMCHAT:
            if self.gmHandler:
                base.talkAssistant.sendOpenTalk(self.gmHandler.getPhrase(textId))
            
            return None
        
        if self.mode == 'PlayerWhisper':
            if questFlag:
                base.talkAssistant.sendPlayerWhisperQuestSpeedChat(questInt, questMsgType, taskNum, self.whisperId)
            else:
                base.talkAssistant.sendPlayerWhisperSpeedChat(msgType, textId, self.whisperId)
        elif self.mode == 'AvatarWhisper':
            if questFlag:
                base.talkAssistant.sendAvatarWhisperQuestSpeedChat(questInt, questMsgType, taskNum, self.whisperId)
            else:
                base.talkAssistant.sendAvatarWhisperSpeedChat(msgType, textId, self.whisperId)
        elif self.mode == 'GuildChat':
            if questFlag:
                base.talkAssistant.sendGuildSCQuestChat(questMsgType, questInt, taskNum)
            else:
                base.talkAssistant.sendGuildSpeedChat(msgType, textId)
        elif self.mode == 'CrewChat':
            if questFlag:
                base.talkAssistant.sendPartySCQuestChat(questMsgType, questInt, taskNum)
            else:
                base.talkAssistant.sendPartySpeedChat(msgType, textId)
        elif self.mode == 'ShipPVP':
            if questFlag:
                base.talkAssistant.sendShipPVPCrewSCQuestChat(questInt, questMsgType, taskNum)
            else:
                base.talkAssistant.sendShipPVPCrewSpeedChat(msgType, textId)
        elif questFlag:
            base.talkAssistant.sendSCQuestChat(questMsgType, questInt, taskNum)
        else:
            base.talkAssistant.sendOpenSpeedChat(msgType, textId)

    
    def handleStaticTextMsg(self, textId):
        if textId in PLocalizer.EmoteMessagesSelf:
            self.handleEmoteMsg(textId)
        elif textId == EmoteGlobals.EMOTE_VALENTINES:
            self.handleEmoteMsg(textId)
        else:
            self.sendChatByMode(SPEEDCHAT_NORMAL, textId)
            self.hide()

    
    def handleGMTextMsg(self, textId):
        self.sendChatByMode(GMCHAT, textId)
        self.hide()

    
    def handleCustomMsg(self, textId):
        self.sendChatByMode(SPEEDCHAT_CUSTOM, textId)
        self.hide()

    
    def handleEmoteMsg(self, emoteId):
        sendText = True
        for prereq in EmoteGlobals.getEmotePrereqs(emoteId):
            if not prereq.avIsReady(localAvatar):
                return None
                continue
        
        if emoteId in OTPLocalizer.Emotes:
            sendText = localAvatar.requestEmote(emoteId)
        
        if sendText:
            if emoteId == EmoteGlobals.EMOTE_VALENTINES:
                emoteId = random.choice([
                    EmoteGlobals.EMOTE_VALENTINES_A,
                    EmoteGlobals.EMOTE_VALENTINES_B,
                    EmoteGlobals.EMOTE_VALENTINES_D,
                    EmoteGlobals.EMOTE_VALENTINES_E])
                self.sendChatByMode(SPEEDCHAT_NORMAL, emoteId)
            else:
                self.sendChatByMode(SPEEDCHAT_EMOTE, emoteId)
        
        self.hide()

    
    def handleEmoteNoAccess(self):
        if self.whisperId is None:
            self.emoteNoAccessPanel.setPos(0, 0, 0)
        else:
            self.emoteNoAccessPanel.setPos(0.37, 0, 0)
        self.emoteNoAccessPanel.reparentTo(aspect2d)

    
    def handleEmoteNoAccessDone(self):
        self.emoteNoAccessPanel.detachNode()

    
    def handleQuestMsg(self, msgType, questInt, toNpcId, taskNum):
        self.sendChatByMode(None, None, questMsgType = msgType, questInt = questInt, taskNum = taskNum, questFlag = 1)
        self.hide()

    
    def handleSpeedChatStyleChange(self):
        (nameKey, arrowColor, rolloverColor, frameColor) = speedChatStyles[base.localAvatar.getSpeedChatStyleIndex()]
        newSCColorScheme = SCColorScheme(arrowColor = arrowColor, rolloverColor = rolloverColor, frameColor = frameColor)
        self.speedChat.setColorScheme(newSCColorScheme)

    
    def createSpeedChatObject(self, structure):
        if hasattr(self, 'speedChat'):
            self.speedChat.exit()
            self.speedChat.destroy()
            del self.speedChat
        
        self.speedChat = SpeedChat(structure = structure, backgroundModelName = 'models/gui/SpeedChatPanel', guiModelName = 'models/textureCards/speedchatIcons')
        self.speedChat.setScale(0.040000000000000001)
        self.speedChat.setBin('gui-popup', 0)
        self.speedChat.setTopLevelOverlap(0.0)
        self.speedChat.setSubmenuOverlap(0.0)
        self.speedChat.setColorScheme(self.DefaultSCColorScheme)
        self.speedChat.finalizeAll()
        self.structure = structure

    
    def addGMSpeedChat(self):
        if not self.gmHandler:
            self.gmHandler = SpeedChatGMHandler.SpeedChatGMHandler()
            self.structure.insert(0, self.gmHandler.getStructure())
            self.speedChat.rebuildFromStructure(self.structure)
        

    
    def addFactoryMenu(self):
        fMenu = PSCFactoryMenu()
        fMenuHolder = SCMenuHolder(OTPLocalizer.SCMenuFactory, menu = fMenu)
        self.speedChat[2:2] = [
            fMenuHolder]

    
    def removeFactoryMenu(self):
        fMenu = self.speedChat[2]
        del self.speedChat[2]
        fMenu.destroy()

    
    def addCogMenu(self, indices):
        fMenu = PSCCogMenu(indices)
        fMenuHolder = SCMenuHolder(OTPLocalizer.SCMenuCog, menu = fMenu)
        self.speedChat[2:2] = [
            fMenuHolder]

    
    def removeCogMenu(self):
        fMenu = self.speedChat[2]
        del self.speedChat[2]
        fMenu.destroy()