using System;
using System.Linq;
using Cirno.Scripts.Components.FSM.Enemy;
using Cirno.Scripts.Resources;
using Cirno.Scripts.Resources.Loot;
using Cirno.Scripts.Utils;
using Godot;

namespace Cirno.Scripts.Actors;

[Tool]
public partial class RogueliteEnemySpawner : Marker2D, IActivable
{
    private EnemyResource _enemy;

    [Export]
    public EnemyResource Enemy
    {
        get => _enemy;
        set
        {
            _enemy = value;
            if (Engine.IsEditorHint())
            {
                QueueRedraw();
            }
        }
    }

    private bool _autoSpawn = false;

    [Export]
    public bool AutoSpawn
    {
        get => _autoSpawn;
        set
        {
            _autoSpawn = value;
            if (Engine.IsEditorHint())
            {
                QueueRedraw();
            }
        }
    } 

    [Export] public int Wave { get; private set; } = 0;

    public bool Spawned { get; private set; } = false;
    
    [Export] public Path2D Path { get; private set; }

    [ExportToolButton("Update Icon")] public Callable RedrawButton => Callable.From(Redraw);

    private EnemyFSMProxy _spawnedEnemy;

    public override void _Draw()
    {
        if (!Engine.IsEditorHint()) return;
        if (Enemy is null) return;
        if (Enemy.IconSprite is null) return;

        var modulate = AutoSpawn ? new Color(1.0f, 1.0f, 1.0f, 1.0f) : new Color(1.0f, 1.0f, 1.0f, 0.5f);
        
        DrawTexture(Enemy.IconSprite, - new Vector2(_enemy.IconSprite.GetWidth() / 2f, _enemy.IconSprite.GetHeight() / 2f), modulate);
        
    }

    private void Redraw()
    {
        QueueRedraw();
    }

    public override void _Ready()
    {
        if (Engine.IsEditorHint()) return;
        if (!AutoSpawn) return;

        Spawn();

    }

    public EnemyFSMProxy Spawn()
    {
        if (Engine.IsEditorHint()) return null;
        if (Spawned) return _spawnedEnemy;
        
        var enemyScene = GD.Load<PackedScene>(Enemy.PrefabPath);
        
        _spawnedEnemy = this.CreateSibling<EnemyFSMProxy>(enemyScene);
        _spawnedEnemy.Init(Enemy);
        Spawned = true;
        
        _spawnedEnemy.Death += SpawnedEnemyOnDeath;
        return _spawnedEnemy;
    }

    public EnemyFSMProxy Spawn(RogueliteMapTheme mapTheme)
    {
        if (Engine.IsEditorHint()) return null;
        if (Spawned) return _spawnedEnemy;

        var spawnedEnemy = Spawn();

        spawnedEnemy.OverrideLoot = true;
        spawnedEnemy.ExtraLoot.Add(new LootDrop()
        {
            Item = mapTheme.EnemiesLootTable.Items.ToList().Shuffle().First(),
            Chance = mapTheme.EnemyDropChance
        });
        
        spawnedEnemy.ExtraLoot.Add(new LootDrop()
        {
            Item = mapTheme.PointItemResource,
            Chance = 100
        });
        
        return spawnedEnemy;
    }

    private void SpawnedEnemyOnDeath(EnemyFSMProxy enemy)
    {
        _spawnedEnemy.Death -= SpawnedEnemyOnDeath;
        _spawnedEnemy = null;
        Spawned = false;
    }

    public bool Activate(ActivationType activationType = ActivationType.Toggle)
    {
        switch (activationType)
        {
            case ActivationType.Toggle:
                Spawn();
                break;
            case ActivationType.Enable:
                break;
            case ActivationType.Disable:
                break;
            case ActivationType.Use:
                break;
            case ActivationType.Destroy:
                break;
            case ActivationType.Open:
                break;
            case ActivationType.Close:
                break;
            default:
                throw new ArgumentOutOfRangeException(nameof(activationType), activationType, null);
        }

        return true;
    }
}