from direct.directnotify import DirectNotifyGlobal
from otp.ai.MagicWordGlobal import *
from toontown.estate.DistributedPlantBaseAI import DistributedPlantBaseAI
import GardenGlobals, time

ONE_DAY = 86400

PROBLEM_WILTED = 1
PROBLEM_NOT_GROWN = 2
PROBLEM_HARVESTED_LATELY = 4

class DistributedGagTreeAI(DistributedPlantBaseAI):
    notify = DirectNotifyGlobal.directNotify.newCategory('DistributedGagTreeAI')
    GrowRate = config.GetBool('trees-grow-rate', 2)

    def __init__(self, mgr):
        DistributedPlantBaseAI.__init__(self, mgr)
        self.wilted = 0
        
    def announceGenerate(self):
        DistributedPlantBaseAI.announceGenerate(self)
        messenger.send(self.getEventName('generate'))
    
    def setWilted(self, wilted):
        self.wilted = wilted
        
    def d_setWilted(self, wilted):
        self.sendUpdate('setWilted', [wilted])
        
    def b_setWilted(self, wilted):
        self.setWilted(wilted)
        self.d_setWilted(wilted)
        
    def getWilted(self):
        return self.wilted
        
    def calculate(self, lastHarvested, lastCheck):
        now = int(time.time())
        if lastCheck == 0:
            lastCheck = now
            
        grown = 0
        
        # Water level
        elapsed = now - lastCheck
        while elapsed > ONE_DAY:
            if self.waterLevel >= 0:
                grown += self.GrowRate
                
            elapsed -= ONE_DAY
            self.waterLevel -= 1
            
        self.waterLevel = max(self.waterLevel, -2)
        
        # Growth level
        maxGrowth = self.growthThresholds[2]
        newGL = min(self.growthLevel + grown, maxGrowth)
        self.setGrowthLevel(newGL)

        self.setWilted(self.waterLevel == -2)
        
        self.lastCheck = now - elapsed
        self.lastHarvested = lastHarvested
        self.update()
        
    def calcDependencies(self):
        if self.getWilted():
            return
            
        missingPrevIndex = 0
        track, value = GardenGlobals.getTreeTrackAndLevel(self.typeIndex)
        while value:
            value -= 1
            if not self.mgr.hasTree(track, value):
                self.b_setWilted(1)
                continue
                
            tree = self.mgr.getTree(track, value)
            if not tree:
                self.b_setWilted(1)
                continue
            
            self.accept(self.getEventName('going-down', 666), self.ignoreAll)
            self.accept(self.getEventName('remove', track * 7 + value), self.calcDependencies)
            
    def getEventName(self, string, typeIndex=None):
        typeIndex = typeIndex if typeIndex is not None else self.typeIndex
        return 'garden-%d-%d-%s' % (self.ownerDoId, typeIndex, string)
                
    def delete(self):
        messenger.send(self.getEventName('remove'))
        self.ignoreAll()
        DistributedPlantBaseAI.delete(self)
        
    def update(self):
        mdata = map(list, self.mgr.data['trees'])
        mdata[self.treeIndex] = [self.typeIndex, self.waterLevel, self.lastCheck, self.getGrowthLevel(), self.lastHarvested]
        self.mgr.data['trees'] = mdata
        self.mgr.update()
        
    def isFruiting(self):
        problem = 0
        if self.getWilted():
            problem |= PROBLEM_WILTED
            
        if self.getGrowthLevel() < self.growthThresholds[2]:
            problem |= PROBLEM_NOT_GROWN
            
        if (self.lastCheck - self.lastHarvested) < ONE_DAY:
            problem |= PROBLEM_HARVESTED_LATELY
            
        return problem
        
    def getFruiting(self):
        return self.isFruiting() == 0
        
    def requestHarvest(self):
        avId = self.air.getAvatarIdFromSender()
        av = self.air.doId2do.get(avId)
        if not av:
            return
        
        if avId != self.ownerDoId:
            self.air.writeServerEvent('suspicious', avId, 'tried to harvest someone else\'s tree!')
            return

        problem = self.isFruiting()
        if problem:
            self.air.writeServerEvent('suspicious', avId, 'tried to harvest a tree that\'s not fruiting!', problem=problem)
            return

        harvested = 0
        track, level = GardenGlobals.getTreeTrackAndLevel(self.typeIndex)
        while av.inventory.addItem(track, level) > 0 and harvested < 10:
            harvested += 1
  
        av.d_setInventory(av.getInventory())
        
        self.lastHarvested = int(time.time())
        self.sendUpdate('setFruiting', [self.getFruiting()])
        self.d_setMovie(GardenGlobals.MOVIE_HARVEST)
        self.update()
        
    def removeItem(self):
        avId = self.air.getAvatarIdFromSender()
        self.d_setMovie(GardenGlobals.MOVIE_REMOVE)
        
        def _remove(task):
            if not self.air:
                return
                
            plot = self.mgr.placePlot(self.treeIndex)
            plot.setPlot(self.plot)
            plot.setPos(self.getPos())
            plot.setH(self.getH())
            plot.setOwnerIndex(self.ownerIndex)
            plot.generateWithRequired(self.zoneId)
            
            self.air.writeServerEvent('remove-tree', avId, plot=self.plot)
            self.requestDelete()
            
            self.mgr.trees.remove(self)
            
            mdata = map(list, self.mgr.data['trees'])
            mdata[self.treeIndex] = self.mgr.getNullPlant()
            self.mgr.data['trees'] = mdata
            self.mgr.update()
            
            self.mgr.reconsiderAvatarOrganicBonus()
            
            return task.done
        
        taskMgr.doMethodLater(7, _remove,  self.uniqueName('do-remove'))
        
    def doGrow(self, grown):
        maxGrowth = self.growthThresholds[2]
        newGL = max(0, min(self.growthLevel + grown, maxGrowth))
        oldGrowthLevel = self.growthLevel
        
        self.b_setGrowthLevel(newGL)
        self.update()
        
        return newGL - oldGrowthLevel
        
@magicWord(category=CATEGORY_PROGRAMMER, types=[int, int, int])
def satanGrow(track, index, grown=21):
    av = spellbook.getTarget()
    estate = av.air.estateManager._lookupEstate(av)
    
    if not estate:
        return 'Estate not found!'
        
    garden = estate.gardenManager.gardens.get(av.doId)
    if not garden:
        return 'Garden not found!'
    
    tree = garden.getTree(track, index)
    if not tree:
        return 'Tree not found!'
        
    result = tree.doGrow(grown)
    return 'Satan has grown %d units!' % result
    
@magicWord(category=CATEGORY_PROGRAMMER, types=[int, int])
def satanFruit(track, index):
    av = spellbook.getTarget()
    estate = av.air.estateManager._lookupEstate(av)
    
    if not estate:
        return 'Estate not found!'
        
    garden = estate.gardenManager.gardens.get(av.doId)
    if not garden:
        return 'Garden not found!'
    
    tree = garden.getTree(track, index)
    if not tree:
        return 'Tree not found!'

    tree.calculate(0, tree.lastCheck)
    tree.sendUpdate('setFruiting', [tree.getFruiting()])
    return 'Satan is now fruiting!'