using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(menuName = project_name + "/" + nameof(SpawnerTile))]
public class SpawnerTile : LevelTile
{
    [SerializeField]
    private GameObject _prefab;
    [SerializeField]
    private bool _spawnOnStart;
    private float _lifetime;
    [SerializeField]
    private float _spawnSpeed = 1.0f;
    [SerializeField, Range(0, 1.001f)]
    private float _spawnCounter = 0;
    private WaveObserver _observer;
    private bool _stopped = false;
    private bool _cooldownEnded = false;
    private bool _EnemiesCleared = true;
    private List<float> _groupSpawnTimers = new List<float>();

    public void SetGroupSpawnTimers(List<float> groupSpawnTimers)
    {
        for (int i = 0; i < groupSpawnTimers.Count; i++)
        {
            _groupSpawnTimers.Add(groupSpawnTimers[i]);
        }
    }


    public override void LevelStart()
    {
        _observer = WaveObserver.Instance;
        _observer.Attach(this);
        if (_spawnOnStart && _lifetime <= 0)
        {
            TriggerSpawn(_prefab);
            _observer.NotifyOnStart(this);
        }
    }

    public override void LevelUpdate()
    {
        _lifetime += Time.deltaTime;
        if (!_stopped)
        {
            _spawnCounter += Time.deltaTime;
        }
        if (_groupSpawnTimers.Count > 0)
        {
            if (_lifetime / 60.0f > _groupSpawnTimers[0])
            {
                _EnemiesCleared = _observer.NotifyGroupSpawn();
                if (_EnemiesCleared)  //Moves on to next group
                {
                    _groupSpawnTimers.RemoveAt(0);
                } else  //Adds a delay to finish current group
                {
                    _groupSpawnTimers[0] += GlobalConfig.Instance.Current.groupSpawnDelay;
                }
            }
        }
        if (_spawnCounter < _spawnSpeed) return;
        _spawnCounter = 0;
        if (!_cooldownEnded)
        {
            _observer.NotifyEndCooldown(this);
            _cooldownEnded = true;
            return;
        }
        TriggerSpawn(_prefab);
        _observer.NotifySpawned(this);
    }
    public override bool Equals(ILevelObject other)
    {
        return other is SpawnerTile spawner
            && base.Equals(spawner)
            && spawner._prefab == _prefab
            && spawner._spawnSpeed == _spawnSpeed;
    }
    public override Dictionary<string, object> ToDictionary()
    {
        var dict = base.ToDictionary();

        dict[nameof(_prefab)] = _prefab.name;
        dict[nameof(_spawnSpeed)] = _spawnSpeed;
        dict[nameof(_spawnCounter)] = _spawnCounter;
        dict[nameof(_lifetime)] = _lifetime;
        dict[nameof(_spawnOnStart)] = _spawnOnStart;
        return dict;
    }

    internal void StopSpawn()
    {
        _stopped = true;
    }

    internal void StartSpawn()
    {
        _stopped = false;
    }


    public override void LoadDictionary(Dictionary<string, object> dict)
    {
        base.LoadDictionary(dict);

        var prefabName = dict[nameof(_prefab)].ToString();
        _prefab = Database.Instance.Prefabs[prefabName];
        _spawnSpeed = dict[nameof(_spawnSpeed)].ToFloat();
        _spawnCounter = dict[nameof(_spawnCounter)].ToFloat();
        _lifetime = dict[nameof(_lifetime)].ToFloat();
        _spawnOnStart = dict[nameof(_spawnOnStart)].ToBool();
    }

    public GameObject Prefab
    {
        set
        {
            _prefab = value;
        }
        get
        {
            return _prefab;
        }
    }

    /**
     * Called by observer
     * Assigns a new spawn interval
     */
    public void ChangeSpawnSpeed(float value)
    {
        _spawnSpeed = value;
    }

    /**
     * Instantly spawns an enemy.
     * Used for GroupSpawn
     */
    public void TriggerSpawn(GameObject enemy)
    {
        enemy.Create(Position, parent: LevelManager.Instance.LevelTransform);
    }

#if UNITY_EDITOR
    [Header("DEBUG")]
    [SerializeField]
    private GameObject _debugPrefab;
    public void TriggerSpawnDebug()
    {
        _debugPrefab.Create(Position, parent: LevelManager.Instance.LevelTransform);
    }
#endif
}