package electrosphere.server.ai;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Random;

import electrosphere.entity.Entity;
import electrosphere.game.data.creature.type.ai.AITreeData;
import electrosphere.logger.LoggerInterface;
import electrosphere.server.ai.services.TimerService;

/**
 * Server manager for all entity AIs
 */
public class AIManager {
    
    /**
     * The list of ais
     */
    List<AI> aiList = new LinkedList<AI>();

    /**
     * The map of ai to associated entity
     */
    Map<AI,Entity> aiEntityMap = new HashMap<AI,Entity>();

    /**
     * The map of entity to associated ai
     */
    Map<Entity,AI> entityAIMap = new HashMap<Entity,AI>();

    /**
     * Controls whether the ai manager should simulate each frame or not
     */
    boolean active = true;

    /**
     * The timer service
     */
    TimerService timerService = new TimerService();

    /**
     * The random of the ai
     */
    Random random = null;
    
    /**
     * Constructor
     */
    public AIManager(long seed){
        this.random = new Random(seed);
    }
    
    /**
     * Simulates all AIs currently available
     */
    public void simulate(){
        //exec the services
        execServices();

        //simulate each tree
        if(isActive()){
            for(AI ai : aiList){
                ai.simulate();
            }
        }
    }

    /**
     * Sets the active status of the ai manager
     * @param isActive true to simulate ai each frame, false otherwise
     */
    public void setActive(boolean isActive){
        //turn off ai components if deactivating ai
        if(this.active && !isActive){
            for(AI ai : aiList){
                ai.resetComponents();
            }
        }
        //actually set
        this.active = isActive;
    }

    /**
     * Gets whether the ai manager is active or not
     * @return true if simulating each frame, false otherwise
     */
    public boolean isActive(){
        return active;
    }

    /**
     * Gets the list of all registered AIs
     * @return The list of AIs
     */
    public List<AI> getAIList(){
        return this.aiList;
    }

    /**
     * Attaches an AI to an entity
     * @param entity The entity
     * @param treeData The list of data on trees to be provided
     */
    public void attachAI(Entity entity, List<AITreeData> treeData){
        if(entity == null){
            LoggerInterface.loggerEngine.ERROR(new IllegalArgumentException("Entity provided is null!"));
        }
        AI ai = AI.constructAI(entity, treeData);
        aiList.add(ai);
        entityAIMap.put(entity,ai);
        aiEntityMap.put(ai,entity);
        AI.setAI(entity, ai);
    }

    /**
     * Removes the ai for this entity from the manager
     * @param entity The entity
     */
    public void removeAI(Entity entity){
        AI targetAI = entityAIMap.get(entity);
        aiList.remove(targetAI);
        aiEntityMap.remove(targetAI);
        entityAIMap.remove(entity);
    }

    /**
     * Executes all the services
     */
    private void execServices(){
        timerService.exec();
    }

    /**
     * Gets the timer service
     * @return The timer service
     */
    public TimerService getTimerService(){
        return timerService;
    }

    /**
     * Gets the ai manager's random
     * @return The random
     */
    public Random getRandom(){
        return random;
    }
    
}
