using Godot;
using Newlon.Components.GUI.Seedpackets;
using Newlon.Components.Plants;

namespace Newlon.Components.Level;

public partial class PlantField : Node2D
{
    private Node2D _plantSetter;
    private DisplayResource _resource;
    private Seedpacket _slot;
    private bool _previousCanPlace;
    private ChannelPlayer player;
    [Export] private PackedScene particles;
    public static PlantField Instance {get; private set;}

    public override void _Ready()
    {
        Instance = this;
        _plantSetter = GetChild<Node2D>(0);
        player = GetNode<ChannelPlayer>("PlantPlayer");
    }

    public void SetPlant(Seedpacket slot, DisplayResource resource)
    {
        _resource = resource;
        _slot = slot;
        if (resource == null)
        {
            foreach(var child in _plantSetter.GetChildren())
                child.QueueFree();
        }
        else
        {
            var scene = resource.Scene.Instantiate<Node2D>();
            _plantSetter.AddChild(scene);
            scene.UseParentMaterial = true;
        }
    }

    public void ResetPlant()
    {
        SetPlant(null,null);
    }

    public override void _Process(double delta)
    {
        // Getting and storing global mouse position, setting plant-poiner to it
        var mouse_pos = GetGlobalMousePosition();
        _plantSetter.GlobalPosition = mouse_pos;

        // Getting position in grid coordinates
        var expected_pos = (_plantSetter.GlobalPosition / Utility.Tile).Ceil() * Utility.Tile - new Vector2(20, 14);

        // Checking for boundaries
        bool inBoundary = expected_pos.X > Utility.LeftFieldBoundary.X && expected_pos.X < Utility.RightFieldBoundary.X && expected_pos.Y > Utility.LeftFieldBoundary.Y && expected_pos.Y < Utility.RightFieldBoundary.Y;


        bool canPlace = _resource != null
            && inBoundary
            && PoolContainer.Instance.EntityField[_resource.Layer].ContainsKey(expected_pos) == false
            && RuntimeLevelData.Instance.CheckSpendSun(_resource.Cost);

        // Setting visuals
        if (_previousCanPlace != canPlace)
        {
            if (canPlace)
            {
                Material.Set("shader_parameter/amount", 0);
            }
            else
            {
                Material.Set("shader_parameter/amount", 1);
            }
            Cursor.Instance.plant = canPlace;
            Cursor.Instance.UpdateCursor();
        }
        _previousCanPlace = canPlace;

        if (canPlace)
            _plantSetter.GlobalPosition = expected_pos;
    }

    public override void _UnhandledInput(InputEvent @event)
    {
        if (@event.IsActionPressed("cancel_plant") && _slot != null)
        {
            _slot.ReleaseFocus();
        }

        if (@event.IsActionPressed("primary_action") && _previousCanPlace)
        {
            var plant = _resource.Scene.Instantiate<RuntimePlantData>();
            PoolContainer.Instance.Plants.AddChild(plant);
            plant.GlobalPosition = (_plantSetter.GlobalPosition / Utility.Tile).Ceil() * Utility.Tile - new Vector2(20, 14);
            plant.Resource = (PlantResource)_resource;

            PoolContainer.Instance.EntityField[_resource.Layer].Add(plant.GlobalPosition, plant);

            RuntimeLevelData.Instance.SpendSun(_resource.Cost);

            PoolContainer.Instance.SpawnParticles(particles, plant.GlobalPosition + Vector2.Down * Utility.TileHeight/2.0f);

            player.Play();

            // Unfocusing and recharging slot
            _slot.Recharge();
        }
    }
}
