using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class TreeFieldPopulator : MonoBehaviour {

    public GameObject TreePrefab = null;
    public GameObject TractorPrefab = null;
    public GameObject HousePrefab = null;

    [Range(1, 50)]
    public float XVariance = 1.0f;

    [Range(1, 50)]
    public float ZVariance = 1.0f;

    [Range(0, 5)]
    public float MinDistanceBetweenTrees;

    public LevelDefinition LevelToPlay;

    public LevelDefinition[] AllAvailableLevels;

    // Use this for initialization
    void Start() {
        if (LevelToPlay == null)
        {
            int lvlIndex = PlayerStats.NextLevel;
            if (lvlIndex >= AllAvailableLevels.Length)
                lvlIndex = AllAvailableLevels.Length - 1;
            LevelToPlay = AllAvailableLevels[lvlIndex];
        }

        Random.InitState(System.DateTime.Now.Millisecond);

        SpawnLevel(LevelToPlay);


        for (int i = 0; i < LevelToPlay.numInitialFires; i++)
        {
            LightRandomTreeOnFire();
        }

        PlaceTractor();

        Minimap mm = GetComponent<Minimap>();
        mm.Reset();

    }

    // Helper Utility functions
    private float JitterAmount { get { return LevelToPlay.JitterAmount; } }
    private float StepSize{ get { return LevelToPlay.StepSize; } }

    void SpawnLevel(LevelDefinition level)
    {
        foreach (PopulationGroup pg in level.SpawnGroups)
        {
            pg.OriginX = Random.Range(-500.0f, 500.0f);
            pg.OriginY = Random.Range(-500.0f, 500.0f);

            
            for (int passIndex = 0; passIndex < pg.Passes.Length; passIndex++)
            {
                if (pg.Passes[passIndex].Enabled)
                    PlaceObjectsUsingPerlinNoise(pg.Passes[passIndex], pg.OriginX, pg.OriginY);
            }

        }

    }

    void PlaceTractor()
    {
        GameObject.Instantiate(TractorPrefab, new Vector3(Random.Range(-10.0f, 10.0f), 0.0f, Random.Range(-10.0f, 10.0f)), Quaternion.identity);
    }

    void LightRandomTreeOnFire()
    {
        // Pick a tree to light on fire
        float searchDistance = LevelToPlay.FireDistance;

        Tree t = null;
        for (int i = 0; i < 99; i++) // try up to 99 times
        {
            Collider[] objList = Tree.GetGameLogicObjectsInRange(Vector3.zero, searchDistance);

            if (objList.Length > 0)
            {
                t = objList[Random.Range(0, objList.Length)].GetComponent<Tree>();
                if (t != null)
                    break;
            }
            searchDistance += 1.0f;
        }

        if (t != null)
        {
            t.GetComponent<Combustible>().SetOnFire();
        }
    }

    void PlaceObjectsUsingPerlinNoise(PopulationPass perlinPass, float originX = 0.0f, float originY = 0.0f)
    {
        for (float z = -ZVariance; z < ZVariance; z+= StepSize)
        {
            for (float x = -XVariance; x < XVariance; x+= StepSize)
            {
                float val = Mathf.PerlinNoise(originX + x / perlinPass.TileSize, originY + z / perlinPass.TileSize);
                if (val >= perlinPass.NoiseForPlacementMin && val <= perlinPass.NoiseForPlacementMax)
                {
                    if (Random.value < perlinPass.SpawnChance)
                    {
                        Vector3 placementLocation = FindTreeSpawnpointCloseTo(new Vector3(x, 0.0f, z), JitterAmount);

                        if (placementLocation != Vector3.zero)
                        {
                            PlaceObjectAt(perlinPass.SpawnObject, placementLocation);
                        }
                    }
                }
            }
        }
    }

    Vector3 FindTreeSpawnpointCloseTo(Vector3 target, float jitter)
    {
        Vector3 result = target;

        for (int i = 0; i < 10; i++)
        {
            result.x += Random.Range(-jitter, jitter);
            result.z += Random.Range(-jitter, jitter);
            Collider[] closeTreeColliders = Tree.GetGameLogicObjectsInRange(result, MinDistanceBetweenTrees);
            if (closeTreeColliders.Length == 0)
                return result;

            jitter += MinDistanceBetweenTrees; // Increase the jitter bigger and bigger to try and find a spot
        }
        return Vector3.zero;
    }

    void PlaceObjectAt(GameObject objTemplate, Vector3 place)
    {
        GameObject.Instantiate(objTemplate, place, Quaternion.identity);
    }
}
