from direct.distributed.DistributedNodeAI import DistributedNodeAI
from direct.distributed.ClockDelta import *
from direct.fsm import ClassicFSM, State
from direct.fsm import State
from direct.fsm import StateData
from toontown.safezone import DistributedChineseCheckersAI
from toontown.safezone import DistributedCheckersAI
from toontown.safezone import DistributedFindFourAI
from toontown.safezone import GameGlobals

class DistributedPicnicTableAI(DistributedNodeAI):

    def __init__(self, air, zone, name, x, y, z, h, p, r):
        DistributedNodeAI.__init__(self, air)
        self.name = name
        self.zoneId = zone
        self.air = air
        self.seats = [
            None,
            None,
            None,
            None,
            None,
            None]
        self.setPos(x, y, z)
        self.setHpr(h, p, r)
        self.playersSitting = 0
        self.playerIdList = []
        self.checkersZoneId = None
        self.observers = []
        self.allowPickers = []
        self.hasPicked = False
        self.game = None
        self.gameDoId = None
        self.isAccepting = True

    def announceGenerate(self):
        pass

    def delete(self):
        DistributedNodeAI.delete(self)
        self.game = None
        self.gameDoId = None

    def setGameDoId(self, doId):
        self.gameDoId = doId
        self.game = self.air.doId2do.get(doId)

    def requestTableState(self):
        avId = self.air.getAvatarIdFromSender()
        self.getTableState()

    def getTableState(self):
        tableStateList = []
        for x in self.seats:
            if x == None:
                tableStateList.append(0)
                continue
            tableStateList.append(x)

        if self.game and self.game.fsm.getCurrentState().getName() == 'playing':
            self.sendUpdate('setTableState', [
                tableStateList,
                1])
        else:
            self.sendUpdate('setTableState', [
                tableStateList,
                0])

    def sendIsPlaying(self):
        if self.game.fsm.getCurrentState().getName() == 'playing':
            self.sendUpdate('setIsPlaying', [
                1])
        else:
            self.sendUpdate('setIsPlaying', [
                0])

    def announceWinner(self, gameName, avId):
        self.sendUpdate('announceWinner', [
            gameName,
            avId])
        self.gameDoId = None
        self.game = None

    def requestJoin(self, si, x, y, z, h, p, r):
        avId = self.air.getAvatarIdFromSender()
        if self.findAvatar(avId) != None:
            self.notify.warning('Ignoring multiple requests from %s to board.' % avId)
            return None

        av = self.air.doId2do.get(avId)
        if av:
            if av.hp > 0 and self.isAccepting and self.seats[si] == None:
                self.notify.debug('accepting boarder %d' % avId)
                self.acceptBoarder(avId, si, x, y, z, h, p, r)
            else:
                self.notify.debug('rejecting boarder %d' % avId)
                self.sendUpdateToAvatarId(avId, 'rejectJoin', [])
        else:
            self.notify.warning('avid: %s does not exist, but tried to board a picnicTable' % avId)

    def acceptBoarder(self, avId, seatIndex, x, y, z, h, p, r):
        self.notify.debug('acceptBoarder %d' % avId)
        if self.findAvatar(avId) != None:
            return None

        isEmpty = True
        for xx in self.seats:
            if xx != None:
                isEmpty = False
                break
                continue

        if isEmpty == True or self.hasPicked == False:
            self.sendUpdateToAvatarId(avId, 'allowPick', [])
            self.allowPickers.append(avId)

        if self.hasPicked == True:
            self.sendUpdateToAvatarId(avId, 'setZone', [
                self.game.zoneId])

        self.seats[seatIndex] = avId
        self.acceptOnce(self.air.getAvatarExitEvent(avId), self._DistributedPicnicTableAI__handleUnexpectedExit, extraArgs = [
            avId])
        self.timeOfBoarding = globalClock.getRealTime()
        if self.game:
            self.game.informGameOfPlayer()

        self.sendUpdate('fillSlot', [
            avId,
            seatIndex,
            x,
            y,
            z,
            h,
            p,
            r,
            globalClockDelta.localToNetworkTime(self.timeOfBoarding),
            self.doId])
        self.getTableState()

    def requestPickedGame(self, gameNum):
        avId = self.air.getAvatarIdFromSender()
        if self.hasPicked == False and avId in self.allowPickers:
            self.hasPicked = True
            numPickers = len(self.allowPickers)
            self.allowPickers = []
            self.pickGame(gameNum)
            if self.game:
                for x in xrange(numPickers):
                    self.game.informGameOfPlayer()

    def pickGame(self, gameNum):
        if self.game:
            return

        x = 0
        for x in self.seats:
            if x != None:
                x += 1
                continue

        if gameNum == GameGlobals.ChineseCheckersGameIndex:
            if simbase.config.GetBool('want-chinese', 1):
                self.game = DistributedChineseCheckersAI.DistributedChineseCheckersAI(self.air, self.doId, 'chinese', self.getX(), self.getY(), self.getZ() + 2.8300000000000001, self.getH(), self.getP(), self.getR())
                self.sendUpdate('setZone', [
                    self.game.zoneId])

        elif gameNum == GameGlobals.CheckersGameIndex:
            if x <= 2:
                if simbase.config.GetBool('want-checkers', 1):
                    self.game = DistributedCheckersAI.DistributedCheckersAI(self.air, self.doId, 'checkers', self.getX(), self.getY(), self.getZ() + 2.8300000000000001, self.getH(), self.getP(), self.getR())
                    self.sendUpdate('setZone', [
                        self.game.zoneId])

        elif gameNum == GameGlobals.FindFourGameIndex:
            if x <= 2:
                if simbase.config.GetBool('want-findfour', 1):
                    self.game = DistributedFindFourAI.DistributedFindFourAI(self.air, self.doId, 'findFour', self.getX(), self.getY(), self.getZ() + 2.8300000000000001, self.getH(), self.getP(), self.getR())
                    self.sendUpdate('setZone', [
                        self.game.zoneId])

    def requestZone(self):
        if not self.game:
            return

        avId = self.air.getAvatarIdFromSender()
        self.sendUpdateToAvatarId(avId, 'setZone', [
            self.game.zoneId])

    def requestGameZone(self):
        if self.hasPicked == True:
            avId = self.air.getAvatarIdFromSender()
            if self.game:
                self.game.playersObserving.append(avId)

            self.observers.append(avId)
            self.acceptOnce(self.air.getAvatarExitEvent(avId), self.handleObserverExit, extraArgs = [
                avId])
            if self.game:
                if self.game.fsm.getCurrentState().getName() == 'playing':
                    self.sendUpdateToAvatarId(avId, 'setGameZone', [
                        self.checkersZoneId,
                        1])
                else:
                    self.sendUpdateToAvatarId(avId, 'setGameZone', [
                        self.checkersZoneId,
                        0])

    def leaveObserve(self):
        avId = self.air.getAvatarIdFromSender()
        if self.game:
            if avId in self.game.playersObserving:
                self.game.playersObserving.remove(avId)

    def handleObserverExit(self, avId):
        if self.game and avId in self.game.playersObserving:
            if self.game:
                self.game.playersObserving.remove(avId)
                self.ignore(self.air.getAvatarExitEvent(avId))

    def requestExit(self):
        self.notify.debug('requestExit')
        avId = self.air.getAvatarIdFromSender()
        av = self.air.doId2do.get(avId)
        if av:
            if self.countFullSeats() > 0:
                self.acceptExiter(avId)
            else:
                self.notify.debug('Player tried to exit after AI already kicked everyone out')
        else:
            self.notify.warning('avId: %s does not exist, but tried to exit picnicTable' % avId)

    def acceptExiter(self, avId):
        seatIndex = self.findAvatar(avId)
        if seatIndex == None:
            if avId in self.observers:
                self.sendUpdateToAvatarId(avId, 'emptySlot', [
                    avId,
                    255,
                    globalClockDelta.getRealNetworkTime()])

        else:
            self.seats[seatIndex] = None
            self.ignore(self.air.getAvatarExitEvent(avId))
            self.sendUpdate('emptySlot', [
                avId,
                seatIndex,
                globalClockDelta.getRealNetworkTime()])
            self.getTableState()
            numActive = 0
            for x in self.seats:
                if x != None:
                    numActive = numActive + 1
                    continue

            if self.game:
                self.game.informGameOfPlayerLeave()
                self.game.handlePlayerExit(avId)

            if numActive == 0:
                self.isAccepting = True
                if self.game:
                    self.game.handleEmptyGame()
                    self.game.requestDelete()
                    self.game = None
                    self.hasPicked = False

    def _DistributedPicnicTableAI__handleUnexpectedExit(self, avId):
        self.notify.warning('Avatar: ' + str(avId) + ' has exited unexpectedly')
        seatIndex = self.findAvatar(avId)
        if seatIndex == None:
            pass

        self.seats[seatIndex] = None
        self.ignore(self.air.getAvatarExitEvent(avId))
        if self.game:
            self.game.informGameOfPlayerLeave()
            self.game.handlePlayerExit(avId)
            self.hasPicked = False

        self.getTableState()
        numActive = 0
        for x in self.seats:
            if x != None:
                numActive = numActive + 1
                continue

        if numActive == 0 and self.game:
            simbase.air.deallocateZone(self.game.zoneId)
            self.game.requestDelete()
            self.game = None
            self.gameDoId = None

    def informGameOfPlayerExit(self, avId):
        self.game.handlePlayerExit(avId)

    def handleGameOver(self):
        for x in self.observers:
            self.acceptExiter(x)
            self.observers.remove(x)

        if self.game:
            self.game.playersObserving = []

        for x in self.seats:
            if x != None:
                self.acceptExiter(x)
                continue

        self.game = None
        self.gameDoId = None
        self.hasPicked = False

    def findAvatar(self, avId):
        for i in xrange(len(self.seats)):
            if self.seats[i] == avId:
                return i
                continue

    def countFullSeats(self):
        avCounter = 0
        for i in self.seats:
            if i:
                avCounter += 1
                continue

        return avCounter

    def findAvailableSeat(self):
        for i in xrange(len(self.seats)):
            if self.seats[i] == None:
                return i
                continue

    def setCheckersZoneId(self, zoneId):
        self.checkersZoneId = zoneId

    def setTableIndex(self, index):
        self._tableIndex = index

    def getTableIndex(self):
        return self._tableIndex