from random import random, randint

from panda3d.core import Point3, Vec3

from helper import base, pedestrian_spawnpoints, minor_spawnpoints
from people.pedestrian import Pedestrian
from people.player import instance as player


SPAWN_DISTANCE = 10
DESPAWN_DISTANCE = 20
COMMUNITY_SIZE = 10
MINOR_COM_SIZE = 3

NO_DESPAWN_ENEMY_DISTANCE = 10

communities = dict()
lost_souls = set()
allies = []

def reset_communities():
    global communities
    for sp, com in communities.items():
        for pedestrian in com:
            pedestrian.die(True)

    communities = {sp: list() for sp in pedestrian_spawnpoints + minor_spawnpoints}


def spawn_pedestrians(task):
    task.delay = 1
    minor_set = set(minor_spawnpoints)
    for spawnpoint in pedestrian_spawnpoints + minor_spawnpoints:
        radius = spawnpoint.z
        pos = Point3(spawnpoint.x, spawnpoint.y, 0)
        distance = (player.pos - spawnpoint).length()
        if distance < SPAWN_DISTANCE:
            if communities[spawnpoint]:
                continue
            communities[spawnpoint] = [
                Pedestrian(pos + Vec3(random()*radius, random()*radius, 0))
                for _ in range(MINOR_COM_SIZE if spawnpoint in minor_set else COMMUNITY_SIZE)
            ]
        if distance > DESPAWN_DISTANCE:
            for pedestrian in communities[spawnpoint]:
                if not pedestrian.alive:
                    pass
                elif pedestrian.relation == pedestrian.Relation.ALLY:
                    allies.append(pedestrian)
                    continue
                elif pedestrian.relation == pedestrian.Relation.ENEMY:
                    d = (player.pos - pedestrian.pos).length()
                    if d < NO_DESPAWN_ENEMY_DISTANCE:
                        lost_souls.add(pedestrian)
                        continue
                pedestrian.die(True)
            communities[spawnpoint].clear()
    for soul in tuple(lost_souls):
        if not soul.alive:
            lost_souls.discard(soul)
            continue
        distance = (player.pos - soul.pos).length()
        if distance > DESPAWN_DISTANCE:
            lost_souls.discard(soul)
            soul.die()
    return task.again

reset_communities()
base.task_mgr.add(spawn_pedestrians)