from otp.ai.AIBaseGlobal import *
from direct.distributed.ClockDelta import *
from direct.distributed import DistributedObjectAI
import Level
from direct.directnotify import DirectNotifyGlobal
import EntityCreatorAI
from direct.showbase.PythonUtil import Functor, weightedChoice

class DistributedLevelAI(DistributedObjectAI.DistributedObjectAI, Level.Level):
    notify = DirectNotifyGlobal.directNotify.newCategory('DistributedLevelAI')

    def __init__(self, air, zoneId, entranceId, avIds):
        DistributedObjectAI.DistributedObjectAI.__init__(self, air)
        Level.Level.__init__(self)
        self.zoneId = zoneId
        self.entranceId = entranceId
        if len(avIds) <= 0 or len(avIds) > 4:
            self.notify.warning('How do we have this many avIds? avIds: %s' % avIds)
        self.avIdList = avIds
        self.numPlayers = len(self.avIdList)
        self.presentAvIds = list(self.avIdList)
        self.notify.debug('expecting avatars: %s' % str(self.avIdList))

    def setLevelSpec(self, levelSpec):
        self.levelSpec = levelSpec

    def generate(self, levelSpec = None):
        self.notify.debug('generate')
        DistributedObjectAI.DistributedObjectAI.generate(self)
        if levelSpec == None:
            levelSpec = self.levelSpec
        self.initializeLevel(levelSpec)
        self.sendUpdate('setZoneIds', [self.zoneIds])
        self.sendUpdate('setStartTimestamp', [self.startTimestamp])

    def getLevelZoneId(self):
        return self.zoneId

    def getAvIds(self):
        return self.avIdList

    def getEntranceId(self):
        return self.entranceId

    def getBattleCreditMultiplier(self):
        return 1.0

    def delete(self, deAllocZone = True):
        self.notify.debug('delete')
        self.destroyLevel()
        self.ignoreAll()
        if deAllocZone:
            self.air.deallocateZone(self.zoneId)
        DistributedObjectAI.DistributedObjectAI.delete(self)

    def initializeLevel(self, levelSpec):
        self.startTime = globalClock.getRealTime()
        self.startTimestamp = globalClockDelta.localToNetworkTime(self.startTime, bits=32)
        lol = zip([1] * levelSpec.getNumScenarios(), range(levelSpec.getNumScenarios()))
        scenarioIndex = weightedChoice(lol)
        Level.Level.initializeLevel(self, self.doId, levelSpec, scenarioIndex)
        for avId in self.avIdList:
            self.acceptOnce(self.air.getAvatarExitEvent(avId), Functor(self.handleAvatarDisconnect, avId))

        self.allToonsGoneBarrier = self.beginBarrier('allToonsGone', self.avIdList, 3 * 24 * 60 * 60, self.allToonsGone)

    def handleAvatarDisconnect(self, avId):
        try:
            self.presentAvIds.remove(avId)
            DistributedLevelAI.notify.warning('av %s has disconnected' % avId)
        except:
            DistributedLevelAI.notify.warning('got disconnect for av %s, not in list' % avId)

        if not self.presentAvIds:
            self.allToonsGone([])

    def allToonsGone(self, toonsThatCleared):
        DistributedLevelAI.notify.info('allToonsGone')
        if hasattr(self, 'allToonsGoneBarrier'):
            self.ignoreBarrier(self.allToonsGoneBarrier)
            del self.allToonsGoneBarrier
        for avId in self.avIdList:
            self.ignore(self.air.getAvatarExitEvent(avId))

        self.requestDelete()

    def createEntityCreator(self):
        return EntityCreatorAI.EntityCreatorAI(level=self)

    def setOuch(self, penalty):
        avId = self.air.getAvatarIdFromSender()
        av = self.air.doId2do.get(avId)
        self.notify.debug('setOuch %s' % penalty)
        if av and penalty > 0:
            av.takeDamage(penalty)
            if av.getHp() <= 0:
                av.inventory.zeroInv()
                av.d_setInventory(av.inventory.makeNetString())