from direct.gui.DirectGui import *
from panda3d.core import *
from toontown.toonbase.ToontownGlobals import *
from toontown.toonbase.ToonBaseGlobal import *
from direct.interval.IntervalGlobal import *
from direct.distributed.ClockDelta import *
from toontown.toonbase import ToontownGlobals
from direct.showbase import DirectObject
from toontown.toon import ToonDNA
from direct.fsm import ClassicFSM, State, StateData
import ClosetGUI
from direct.task.Task import Task
import ClosetGlobals
import DistributedFurnitureItem
from toontown.toonbase import TTLocalizer

class DistributedCloset(DistributedFurnitureItem.DistributedFurnitureItem):
    notify = directNotify.newCategory('DistributedCloset')

    def __init__(self, cr):
        DistributedFurnitureItem.DistributedFurnitureItem.__init__(self, cr)
        self.notify.debug('__init__')
        self.lastAvId = 0
        self.hasLocalAvatar = 0
        self.lastTime = 0
        self.av = None
        self.closetGUI = None
        self.closetModel = None
        self.closetSphere = None
        self.closetSphereNode = None
        self.closetSphereNodePath = None
        self.topList = []
        self.botList = []
        self.oldTopList = []
        self.oldBotList = []
        self.oldStyle = None
        self.button = None
        self.topTrashButton = None
        self.bottomTrashButton = None
        self.isLocalToon = None
        self.popupInfo = None
        self.isOwner = 0
        self.ownerId = 0
        self.customerId = 0
        self.purchaseDoneEvent = ''
        self.swapEvent = ''
        self.locked = 0
        self.gender = None
        self.topDeleted = 0
        self.bottomDeleted = 0
        self.closetTrack = None
        self.avMoveTrack = None
        self.scale = 1.0
        self.fsm = ClassicFSM.ClassicFSM('Closet', [State.State('off', self.enterOff, self.exitOff, ['ready', 'open', 'closed']),
         State.State('ready', self.enterReady, self.exitReady, ['open', 'closed']),
         State.State('closed', self.enterClosed, self.exitClosed, ['open', 'off']),
         State.State('open', self.enterOpen, self.exitOpen, ['closed', 'off'])], 'off', 'off')
        self.fsm.enterInitialState()
        return

    def generate(self):
        DistributedFurnitureItem.DistributedFurnitureItem.generate(self)

    def announceGenerate(self):
        self.notify.debug('announceGenerate')
        DistributedFurnitureItem.DistributedFurnitureItem.announceGenerate(self)
        self.load()
        self.setupCollisionSphere()
        self.fsm.request('ready')

    def load(self):
        self.setTwoSided(1)
        lNode = self.find('**/door_rotate_L')
        lDoor = self.find('**/closetdoor_L')
        if lNode.isEmpty() or lDoor.isEmpty():
            self.leftDoor = None
        else:
            lDoor.wrtReparentTo(lNode)
            self.leftDoor = lNode
        rNode = self.find('**/door_rotate_R')
        rDoor = self.find('**/closetdoor_R')
        if rNode.isEmpty() or rDoor.isEmpty():
            self.rightDoor = None
        else:
            rDoor.wrtReparentTo(rNode)
            self.rightDoor = rNode
        if not lNode.isEmpty():
            self.scale = lNode.getScale()[0]
        return

    def setupCollisionSphere(self):
        if self.ownerId:
            self.closetSphereEvent = self.uniqueName('closetSphere')
            self.closetSphereEnterEvent = 'enter' + self.closetSphereEvent
            self.closetSphere = CollisionSphere(0, 0, 0, self.scale * 2.125)
            self.closetSphere.setTangible(0)
            self.closetSphereNode = CollisionNode(self.closetSphereEvent)
            self.closetSphereNode.setIntoCollideMask(WallBitmask)
            self.closetSphereNode.addSolid(self.closetSphere)
            self.closetSphereNodePath = self.attachNewNode(self.closetSphereNode)

    def disable(self):
        self.notify.debug('disable')
        self.ignore(self.closetSphereEnterEvent)
        self.ignoreAll()
        taskMgr.remove(self.uniqueName('popupChangeClothesGUI'))
        taskMgr.remove(self.uniqueName('lerpCamera'))
        taskMgr.remove(self.uniqueName('lerpToon'))
        if self.closetTrack:
            self.closetTrack.finish()
            self.closetTrack = None
        if self.closetGUI:
            self.closetGUI.resetClothes(self.oldStyle)
            self.resetCloset()
        if self.hasLocalAvatar:
            self.freeAvatar()
        self.ignoreAll()
        DistributedFurnitureItem.DistributedFurnitureItem.disable(self)
        return

    def delete(self):
        self.notify.debug('delete')
        DistributedFurnitureItem.DistributedFurnitureItem.delete(self)
        if self.popupInfo:
            self.popupInfo.destroy()
            self.popupInfo = None
        if self.av:
            del self.av
        del self.gender
        del self.closetSphere
        del self.closetSphereNode
        del self.closetSphereNodePath
        del self.closetGUI
        del self.fsm
        return

    def enterOff(self):
        pass

    def exitOff(self):
        pass

    def enterReady(self):
        if self.ownerId:
            self.accept(self.closetSphereEnterEvent, self.handleEnterSphere)

    def exitReady(self):
        pass

    def enterOpen(self):
        if self.ownerId:
            self.ignore(self.closetSphereEnterEvent)
            self._openDoors()
            if self.customerId == base.localAvatar.doId:
                camera.wrtReparentTo(self)
                camera.posQuatInterval(1, (-7.58, -6.02, 6.9), (286.3, 336.8, 0), other=self, blendType='easeOut').start()
                camera.setPosHpr(self, -7.58, -6.02, 6.9, 286.3, 336.8, 0)
            if self.av:
                if self.avMoveTrack:
                    self.avMoveTrack.finish()
                self.av.stopSmooth()
                self.avMoveTrack = Sequence(Parallel(Func(self.av.play, 'walk'), LerpPosHprInterval(nodePath=self.av, other=self, duration=1.0, pos=Vec3(1.67, -3.29, 0.025), hpr=Vec3(112, 0, 0), blendType='easeOut')), Func(self.av.loop, 'neutral'), Func(self.av.startSmooth))
                self.avMoveTrack.start()

    def exitOpen(self):
        if self.ownerId:
            self._closeDoors()

    def enterClosed(self):
        if self.ownerId:
            self.accept(self.closetSphereEnterEvent, self.handleEnterSphere)

    def exitClosed(self):
        pass

    def handleEnterSphere(self, collEntry):
        if self.smoothStarted:
            return
        if base.localAvatar.doId == self.lastAvId and globalClock.getFrameTime() <= self.lastTime + 0.5:
            self.notify.info('Ignoring duplicate entry for avatar.')
            return
        if self.hasLocalAvatar:
            self.freeAvatar()
        self.notify.debug('Entering Closet Sphere....%s' % self.closetSphereEnterEvent)
        if self.cr.playGame.getPlace() == None:
            self.notify.info('Not opening closet before place is defined.')
            return
        self.ignore(self.closetSphereEnterEvent)
        if not self.locked:
            self.cr.playGame.getPlace().fsm.request('closet')
            self.accept('closetAsleep', self._handleCancel)
            self.sendUpdate('enterAvatar', [])
            self.hasLocalAvatar = 1
        return

    def setState(self, mode, avId, ownerId, gender, topList, botList):
        self.notify.debug('setState, mode=%s, avId=%s, ownerId=%d' % (mode, avId, ownerId))
        self.isOwner = avId == ownerId
        self.ownerGender = gender
        if mode == ClosetGlobals.CLOSED:
            self.fsm.request('closed')
            return
        elif mode == ClosetGlobals.OPEN:
            self.customerId = avId
            self.av = self.cr.doId2do.get(self.customerId, None)
            if self.av:
                if base.localAvatar.getDoId() == self.customerId:
                    self.gender = self.av.style.gender
                    self.topList = topList
                    self.botList = botList
                    self.oldTopList = self.topList[0:]
                    self.oldBotList = self.botList[0:]
                    self.printInfo()
                    if not self.isOwner:
                        self.__popupNotOwnerPanel()
                    else:
                        taskMgr.doMethodLater(0.5, self.popupChangeClothesGUI, self.uniqueName('popupChangeClothesGUI'))
                self.fsm.request('open')
        return

    def _revertGender(self):
        if self.gender:
            self.av.style.gender = self.gender
            self.av.loop('neutral')

    def popupChangeClothesGUI(self, task):
        self.notify.debug('popupChangeClothesGUI')
        self.purchaseDoneEvent = self.uniqueName('purchaseDone')
        self.swapEvent = self.uniqueName('swap')
        self.cancelEvent = self.uniqueName('cancel')
        self.accept(self.purchaseDoneEvent, self.__proceedToCheckout)
        self.accept(self.swapEvent, self.__handleSwap)
        self.accept(self.cancelEvent, self._handleCancel)
        self.deleteEvent = self.uniqueName('delete')
        if self.isOwner:
            self.accept(self.deleteEvent, self.__handleDelete)
        if not self.closetGUI:
            self.closetGUI = ClosetGUI.ClosetGUI(self.isOwner, self.purchaseDoneEvent, self.cancelEvent, self.swapEvent, self.deleteEvent, self.topList, self.botList)
            self.closetGUI.load()
            if self.gender != self.ownerGender:
                self.closetGUI.setGender(self.ownerGender)
            self.closetGUI.enter(base.localAvatar)
            self.closetGUI.showButtons()
            style = self.av.getStyle()
            self.oldStyle = ToonDNA.ToonDNA()
            self.oldStyle.makeFromNetString(style.makeNetString())
        return Task.done

    def resetCloset(self):
        self.ignoreAll()
        taskMgr.remove(self.uniqueName('popupChangeClothesGUI'))
        taskMgr.remove(self.uniqueName('lerpCamera'))
        taskMgr.remove(self.uniqueName('lerpToon'))
        if self.closetGUI:
            self.closetGUI.hideButtons()
            self.closetGUI.exit()
            self.closetGUI.unload()
            self.closetGUI = None
            del self.av
        self.av = base.localAvatar
        style = self.av.getStyle()
        self.oldStyle = ToonDNA.ToonDNA()
        self.oldStyle.makeFromNetString(style.makeNetString())
        self.topDeleted = 0
        self.bottomDeleted = 0
        return Task.done

    def __handleButton(self):
        messenger.send('next')

    def _handleCancel(self):
        if self.oldStyle:
            self.d_setDNA(self.oldStyle.makeNetString(), 1)
        else:
            self.notify.info('avoided crash in handleCancel')
            self._handlePurchaseDone()
        if self.closetGUI:
            self.closetGUI.resetClothes(self.oldStyle)
        if self.popupInfo != None:
            self.popupInfo.destroy()
            self.popupInfo = None
        return

    def __handleSwap(self):
        self.d_setDNA(self.av.getStyle().makeNetString(), 0)

    def __handleDelete(self, t_or_b):
        if t_or_b == ClosetGlobals.SHIRT:
            itemList = self.closetGUI.tops
            trashIndex = self.closetGUI.topChoice
            swapFunc = self.closetGUI.swapTop
            removeFunc = self.closetGUI.removeTop
            self.topDeleted = self.topDeleted | 1

            def setItemChoice(i):
                self.closetGUI.topChoice = i

        else:
            itemList = self.closetGUI.bottoms
            trashIndex = self.closetGUI.bottomChoice
            swapFunc = self.closetGUI.swapBottom
            removeFunc = self.closetGUI.removeBottom
            self.bottomDeleted = self.bottomDeleted | 1

            def setItemChoice(i):
                self.closetGUI.bottomChoice = i

        if len(itemList) > 1:
            trashDNA = ToonDNA.ToonDNA()
            trashItem = self.av.getStyle().makeNetString()
            trashDNA.makeFromNetString(trashItem)
            if trashIndex == 0:
                swapFunc(1)
            else:
                swapFunc(-1)
            removeFunc(trashIndex)
            self.sendUpdate('removeItem', [trashItem, t_or_b])
            swapFunc(0)
            self.closetGUI.updateTrashButtons()
        else:
            self.notify.warning("cant delete this item(type = %s), since we don't have a replacement" % t_or_b)

    def resetItemLists(self):
        self.topList = self.oldTopList[0:]
        self.botList = self.oldBotList[0:]
        self.closetGUI.tops = self.topList
        self.closetGUI.bottoms = self.botList
        self.topDeleted = 0
        self.bottomDeleted = 0

    def __proceedToCheckout(self):
        if self.topDeleted or self.bottomDeleted:
            self.__popupAreYouSurePanel()
        else:
            self._handlePurchaseDone()

    def _handlePurchaseDone(self, timeout = 0):
        if timeout == 1:
            self.d_setDNA(self.oldStyle.makeNetString(), 1)
        else:
            which = 0
            if hasattr(self.closetGUI, 'topChoice') and hasattr(self.closetGUI, 'bottomChoice'):
                if self.closetGUI.topChoice != 0 or self.topDeleted:
                    which = which | 1
                if self.closetGUI.bottomChoice != 0 or self.bottomDeleted:
                    which = which | 2
            self.d_setDNA(self.av.getStyle().makeNetString(), 2, which)

    def d_setDNA(self, dnaString, finished, whichItems = 3):
        self.sendUpdate('setDNA', [dnaString, finished, whichItems])

    def setCustomerDNA(self, avId, dnaString):
        if avId and avId != base.localAvatar.doId:
            av = base.cr.doId2do.get(avId, None)
            if av:
                if self.av == base.cr.doId2do[avId]:
                    oldTorso = self.av.style.torso
                    self.av.style.makeFromNetString(dnaString)
                    if len(oldTorso) == 2 and len(self.av.style.torso) == 2 and self.av.style.torso[1] != oldTorso[1]:
                        self.av.swapToonTorso(self.av.style.torso, genClothes=0)
                        self.av.loop('neutral', 0)
                    self.av.generateToonClothes()
        return

    def printInfo(self):
        print 'avid: %s, gender: %s' % (self.av.doId, self.av.style.gender)
        print 'current top = %s,%s,%s,%s and  bot = %s,%s,' % (self.av.style.topTex,
         self.av.style.topTexColor,
         self.av.style.sleeveTex,
         self.av.style.sleeveTexColor,
         self.av.style.botTex,
         self.av.style.botTexColor)
        print 'topsList = %s' % self.av.getClothesTopsList()
        print 'bottomsList = %s' % self.av.getClothesBottomsList()

    def setMovie(self, mode, avId, timestamp):
        self.isLocalToon = avId == base.localAvatar.doId
        if avId != 0:
            self.lastAvId = avId
        self.lastTime = globalClock.getFrameTime()
        if mode == ClosetGlobals.CLOSET_MOVIE_CLEAR:
            return
        elif mode == ClosetGlobals.CLOSET_MOVIE_COMPLETE:
            if self.isLocalToon:
                self._revertGender()
                self.printInfo()
                self.resetCloset()
                self.freeAvatar()
                return
        elif mode == ClosetGlobals.CLOSET_MOVIE_TIMEOUT:
            taskMgr.remove(self.uniqueName('lerpCamera'))
            taskMgr.remove(self.uniqueName('lerpToon'))
            if self.isLocalToon:
                self.ignore(self.purchaseDoneEvent)
                self.ignore(self.swapEvent)
                if self.closetGUI:
                    self.closetGUI.resetClothes(self.oldStyle)
                    self._handlePurchaseDone(timeout=1)
                    self.resetCloset()
                self._popupTimeoutPanel()
                self.freeAvatar()

    def freeAvatar(self):
        self.notify.debug('freeAvatar()')
        if self.hasLocalAvatar:
            base.localAvatar.posCamera(0, 0)
            place = base.cr.playGame.getPlace()
            if place:
                place.setState('walk')
            self.ignore('closetAsleep')
            base.localAvatar.startLookAround()
            self.hasLocalAvatar = 0
        self.lastTime = globalClock.getFrameTime()

    def setOwnerId(self, avId):
        self.ownerId = avId

    def _popupTimeoutPanel(self):
        if self.popupInfo != None:
            self.popupInfo.destroy()
            self.popupInfo = None
        buttons = loader.loadModel('phase_3/models/gui/dialog_box_buttons_gui')
        okButtonImage = (buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr'))
        self.popupInfo = DirectFrame(parent=hidden, relief=None, state='normal', text=TTLocalizer.ClosetTimeoutMessage, frameSize=(-1, 1, -1, 1), geom=DGG.getDefaultDialogGeom(), geom_color=ToontownGlobals.GlobalDialogColor, geom_scale=(0.88, 1, 0.45), geom_pos=(0, 0, -.08), text_scale=0.08)
        DirectButton(self.popupInfo, image=okButtonImage, relief=None, text=TTLocalizer.ClosetPopupOK, text_scale=0.05, text_pos=(0.0, -0.1), textMayChange=0, pos=(0.0, 0.0, -0.16), command=self.__handleTimeoutMessageOK)
        buttons.removeNode()
        self.popupInfo.reparentTo(aspect2d)
        return

    def __handleTimeoutMessageOK(self):
        self.popupInfo.reparentTo(hidden)

    def __popupNotOwnerPanel(self):
        if self.popupInfo != None:
            self.popupInfo.destroy()
            self.popupInfo = None
        self.purchaseDoneEvent = self.uniqueName('purchaseDone')
        self.swapEvent = self.uniqueName('swap')
        self.cancelEvent = self.uniqueName('cancel')
        self.accept(self.purchaseDoneEvent, self.__proceedToCheckout)
        self.accept(self.swapEvent, self.__handleSwap)
        self.accept(self.cancelEvent, self._handleCancel)
        self.deleteEvent = self.uniqueName('delete')
        if self.isOwner:
            self.accept(self.deleteEvent, self.__handleDelete)
        buttons = loader.loadModel('phase_3/models/gui/dialog_box_buttons_gui')
        okButtonImage = (buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr'))
        self.popupInfo = DirectFrame(parent=hidden, relief=None, state='normal', text=TTLocalizer.ClosetNotOwnerMessage, frameSize=(-1, 1, -1, 1), text_wordwrap=10, geom=DGG.getDefaultDialogGeom(), geom_color=ToontownGlobals.GlobalDialogColor, geom_scale=(0.88, 1, 0.55), geom_pos=(0, 0, -.08), text_scale=0.08, text_pos=(0, 0.06))
        DirectButton(self.popupInfo, image=okButtonImage, relief=None, text=TTLocalizer.ClosetPopupOK, text_scale=0.05, text_pos=(0.0, -0.1), textMayChange=0, pos=(0.0, 0.0, -0.21), command=self._handleNotOwnerMessageOK)
        buttons.removeNode()
        self.popupInfo.reparentTo(aspect2d)
        return

    def _handleNotOwnerMessageOK(self):
        self.popupInfo.reparentTo(hidden)
        taskMgr.doMethodLater(0.1, self.popupChangeClothesGUI, self.uniqueName('popupChangeClothesGUI'))

    def __popupAreYouSurePanel(self):
        if self.popupInfo != None:
            self.popupInfo.destroy()
            self.popupInfo = None
        buttons = loader.loadModel('phase_3/models/gui/dialog_box_buttons_gui')
        okButtonImage = (buttons.find('**/ChtBx_OKBtn_UP'), buttons.find('**/ChtBx_OKBtn_DN'), buttons.find('**/ChtBx_OKBtn_Rllvr'))
        cancelButtonImage = (buttons.find('**/CloseBtn_UP'), buttons.find('**/CloseBtn_DN'), buttons.find('**/CloseBtn_Rllvr'))
        self.popupInfo = DirectFrame(parent=hidden, relief=None, state='normal', text=TTLocalizer.ClosetAreYouSureMessage, frameSize=(-1, 1, -1, 1), text_wordwrap=10, geom=DGG.getDefaultDialogGeom(), geom_color=ToontownGlobals.GlobalDialogColor, geom_scale=(0.88, 1, 0.55), geom_pos=(0, 0, -.08), text_scale=0.08, text_pos=(0, 0.08))
        DirectButton(self.popupInfo, image=okButtonImage, relief=None, text=TTLocalizer.ClosetPopupOK, text_scale=0.05, text_pos=(0.0, -0.1), textMayChange=0, pos=(-0.1, 0.0, -0.21), command=self._handleYesImSure)
        DirectButton(self.popupInfo, image=cancelButtonImage, relief=None, text=TTLocalizer.ClosetPopupCancel, text_scale=0.05, text_pos=(0.0, -0.1), textMayChange=0, pos=(0.1, 0.0, -0.21), command=self._handleNotSure)
        buttons.removeNode()
        self.popupInfo.reparentTo(aspect2d)
        return

    def _handleYesImSure(self):
        self.popupInfo.reparentTo(hidden)
        self._handlePurchaseDone()

    def _handleNotSure(self):
        self.popupInfo.reparentTo(hidden)

    def _openDoors(self):
        if self.closetTrack:
            self.closetTrack.finish()
        leftHpr = Vec3(-110, 0, 0)
        rightHpr = Vec3(110, 0, 0)
        self.closetTrack = Parallel()
        if self.rightDoor:
            self.closetTrack.append(self.rightDoor.hprInterval(0.5, rightHpr))
        if self.leftDoor:
            self.closetTrack.append(self.leftDoor.hprInterval(0.5, leftHpr))
        self.closetTrack.start()

    def _closeDoors(self):
        if self.closetTrack:
            self.closetTrack.finish()
        leftHpr = Vec3(0, 0, 0)
        rightHpr = Vec3(0, 0, 0)
        self.closetTrack = Parallel()
        if self.rightDoor:
            self.closetTrack.append(self.rightDoor.hprInterval(0.5, rightHpr))
        if self.leftDoor:
            self.closetTrack.append(self.leftDoor.hprInterval(0.5, leftHpr))
        self.closetTrack.start()
