package electrosphere.server.simulation;

import electrosphere.engine.Globals;
import electrosphere.game.server.structure.virtual.Structure;
import electrosphere.game.server.town.Town;
import electrosphere.game.server.character.Character;
import electrosphere.game.server.character.CharacterDataStrings;
import electrosphere.game.server.character.CharacterUtils;
import electrosphere.game.server.structure.virtual.StructureDataStrings;
import electrosphere.game.server.structure.virtual.VirtualStructureUtils;
import java.util.LinkedList;
import java.util.List;
import org.joml.Vector2f;
import org.joml.Vector2i;

public class MacroSimulation {
    
//    List<Civilization> civilizationList = new LinkedList();
//    List<Culture> cultureList = new LinkedList();
//    List<Religion> religionList = new LinkedList();
//    List<CreatureType> creatureList = new LinkedList();
//    List<Character> characterList = new LinkedList();
//    List<Town> townList = new LinkedList();
//    List<Structure> structureList = new LinkedList();
    
    boolean isReady = false;
    
    public MacroSimulation(){
    }
    
    void init(){
//        CreatureTypeMap creatureTypeMap = FileLoadingUtils.loadObjectFromAssetPath("Data/creatures.json", CreatureTypeMap.class);
//        CivilizationMap civilizationMap = FileLoadingUtils.loadObjectFromAssetPath("Data/civilization.json", CivilizationMap.class);
    }
    
    public void simulate(){
        for(Character character : Globals.macroData.getAliveCharacters()){
            //do something
            checkForShelter(character);
            checkTownMembership(character);
        }
    }
    
    public void setReady(boolean status){
        isReady = status;
    }
    
    public boolean isReady(){
        return isReady;
    }
    
    static final int MAX_PLACE_ATTEMPTS = 10;
    
    static void checkForShelter(Character chara){
//        for(Character chara : Globals.macroData.getAliveCharacters()){
        /*
        If doesn’t have shelter, check if in town
        If in town,
            check if there’s an inn/church/friendly family
                if so, try to stay there
            if can’t find place to stay, fashion makeshift shelter
        If no town
            fashion makeshift shelter
        */
        if(!chara.containsKey(CharacterDataStrings.SHELTER)){
            Vector2i charPos = CharacterUtils.getDiscretePosition(chara);
            Town nearbyTown = Town.getTownAtPosition(charPos.x,charPos.y);
            if(nearbyTown != null){
                //if town has a place to stay
                if(false){

                } else {
                    //try to find a place to put down a structure

                }
            } else {
                //cry
                //TODO: Get building type to place
                String buildingTypeToPlace = "building1";
                //try to find a place to put down a structure
                // int dynamicInterpRatio = Globals.serverTerrainManager.getDynamicInterpolationRatio();
                // Vector2f placementPos = new Vector2f(
                //         (float)(charPos.x * dynamicInterpRatio + Math.random() * dynamicInterpRatio),
                //         (float)(charPos.y * dynamicInterpRatio + Math.random() * dynamicInterpRatio)
                // );
                // int attempts = 0;
                // while(!VirtualStructureUtils.validStructurePlacementPosition(placementPos.x, placementPos.y, buildingTypeToPlace)){
                //     placementPos = new Vector2f(
                //         (float)(charPos.x * dynamicInterpRatio + Math.random() * dynamicInterpRatio),
                //         (float)(charPos.y * dynamicInterpRatio + Math.random() * dynamicInterpRatio)
                //     );
                //     attempts++;
                //     if(attempts > MAX_PLACE_ATTEMPTS){
                //         placementPos = null;
                //         break;
                //     }
                // }
                // if(placementPos != null){
                //     // Structure placedStructure = VirtualStructureUtils.placeStructureAtPoint(placementPos.x, placementPos.y, buildingTypeToPlace);
                //     // CharacterUtils.addShelter(chara, placedStructure);
                //     // VirtualStructureUtils.addResident(placedStructure, chara);
                // }
            }
        }
//        }
    }
    
    static void checkTownMembership(Character chara){
        //TODO: eventually exclude people who shouldn't belong to a town (traders, bandits, etc)
//        for(Character chara : Globals.macroData.getAliveCharacters()){
        boolean hasHometown = chara.containsKey(CharacterDataStrings.HOMETOWN);
        boolean hasShelter = chara.containsKey(CharacterDataStrings.SHELTER);
        //if has structure & no hometown
        if(!hasHometown && hasShelter){
            Structure shelter = CharacterUtils.getShelter(chara);
            //if there's at least one other structure nearby
            Vector2i shelterDiscretePos = new Vector2i(shelter.getWorldX(),shelter.getWorldY());
            List<Structure> nearbyPopulatedStructures = new LinkedList<Structure>();
            for(Structure currentStruct : Globals.macroData.getStructures()){
                if(currentStruct.getWorldX() == shelterDiscretePos.x && currentStruct.getWorldY() == shelterDiscretePos.y && currentStruct != shelter){
                    //if has a resident
                    if(shelter.getDataKeys().contains(StructureDataStrings.RESIDENTS) && VirtualStructureUtils.getResidents(shelter).size() > 0){
                        boolean noTown = true;
                        for(Town town : Globals.macroData.getTowns()){
                            if(town.getStructures().contains(currentStruct)){
                                noTown = false;
                            }
                        }
                        if(noTown){
                            nearbyPopulatedStructures.add(currentStruct);
                        }
                    }
                }
            }
            if(nearbyPopulatedStructures.size() > 0){
                int numStructures = 0;
                int numResidents = 0;
                //form town
                Town newTown = Town.createTown(shelterDiscretePos.x, shelterDiscretePos.y);
                for(Structure structure : nearbyPopulatedStructures){
                    numStructures++;
                    newTown.addStructure(structure);
                    for(Character resident : VirtualStructureUtils.getResidents(structure)){
                        numResidents++;
                        newTown.addResident(resident);
                        CharacterUtils.addHometown(resident, newTown);
                    }
                }
                newTown.addStructure(shelter);
                newTown.addResident(chara);
                CharacterUtils.addHometown(chara, newTown);
                System.out.println("Formed town with " + numStructures + " structures and " + numResidents + " residents");
            }
        }
//        }
    }
    
    static void checkInitCombat(){
        for(Character chara : Globals.macroData.getAliveCharacters()){
            Vector2i position = CharacterUtils.getDiscretePosition(chara);
        }
    }
}
