using System;
using System.Collections;
using System.Threading;
using System.Threading.Tasks;
using Cirno.Scripts.Components.FSM;
using Godot;
using GTweensGodot.Extensions;

namespace Cirno.Scripts.Activables;

[Tool]
public partial class Teleporter : Activable
{
    [Export]
    public bool IsEnabled { get; set; }

    [Export]
    public bool Invisible { get; set; } = false;

    public bool IsPrimed { get; private set; }

    [Export]
    public Teleporter Target { get; set; }

    [Export] public float ParticleEmitTime { get; private set; } = 2f;

    [Export] public float TeleportAnimationLength { get; private set; } = 0.5f;

    [Export] public Vector2 TeleportOffset { get; private set; } = new Vector2(0, -4f);

    private double _particleTimer;

    private AnimatedSprite2D _animatedSprite;

    // [Export]
    // public GpuParticles2D Particles { get; set; }

    protected GpuParticles2D _particles;

    private AudioStreamPlayer2D _teleportStartSound;
    private AudioStreamPlayer2D _teleportEndSound;

    public override void _Ready()
    {
        _animatedSprite = GetNode<AnimatedSprite2D>("AnimatedSprite2D");
        _animatedSprite.Play(IsEnabled ? "Active" : "Default");
        if (Engine.IsEditorHint()) return;
        
        _particles = GetNode<GpuParticles2D>("./Particles");
        
        IsPrimed = true;
        _particles.Emitting = false;
        _particleTimer = 0;

        this.Visible = !Invisible;
        
        _teleportStartSound = GetNodeOrNull<AudioStreamPlayer2D>("TeleportStart");
        _teleportEndSound = GetNodeOrNull<AudioStreamPlayer2D>("TeleportEnd");
    }

    public override void _Process(double delta)
    {
        if (Engine.IsEditorHint()) return;
        if (!_particles.Emitting) return;

        _particleTimer += delta;

        if (_particleTimer >= ParticleEmitTime)
        {
            _particleTimer = 0;
            _particles.Emitting = false;
        }
    }

    public override bool Activate(ActivationType activationType = ActivationType.Toggle)
    {
        switch (activationType)
        {
            case ActivationType.Toggle:
                // Enables/Disables teleporter
                break;
            case ActivationType.Enable:
                // Enables Teleporter
                IsEnabled = true;
                _animatedSprite.Play("Active");
                break;
            case ActivationType.Disable:
                IsEnabled = false;
                _animatedSprite.Play("Default");
                // Disables Teleporter
                break;
            case ActivationType.Use:
                // Teleports
                break;
            case ActivationType.Destroy:
                // Destroys
                break;
        }

        return true;
    }

    public void PrepareForReceiving()
    {
        IsPrimed = false;
        _particles.Emitting = true;
    }

    public void FireParticles()
    {
        _particles.Emitting = true;
        _particleTimer = 0;
    }

    private void _on_area_entered(Area2D area)
    {
        GD.Print("Something entered the teleporter");
        if (!IsEnabled) return;
        if (area is not InteractionController interactionController) return;
        GD.Print("Player entered the teleporter");

        if (!IsPrimed)
        {
            IsPrimed = true;
            //_particles.Emitting = false;
            return;
        }

        // Teleport player to target if active
        if (!IsEnabled) return;

        GD.Print("Teleporting...");

        // Call Teleport here
        _ = Teleport(interactionController.StateMachine);
    }

    protected virtual async Task Teleport(IStateMachine<PlayerState, CharacterBody2D> player)
    {
        if (Target is null) return;
        //player.RequestMovementDisable(true);
        player.SetState(PlayerState.Cutscene);

        await TweenPlayer(player.MainObject);

        PlayTeleportStartSound();

        //_particles.Emitting = true;
        FireParticles();

        //await player.Teleport();
        player.SetState(PlayerState.Teleporting);
        await Task.Delay((int)(0.6f * 1000));

        await Task.Delay((int)(TeleportAnimationLength * 1000));

        Target.PrepareForReceiving();
        player.MainObject.GlobalPosition = Target.GlobalPosition + TeleportOffset;
        Target.PlayTeleportEndSound();
        //await player.UnTeleport();

        player.SetState(PlayerState.UnTeleporting);
        await Task.Delay((int)(0.6f * 1000));

        //player.RequestMovementDisable(false);
        player.SetState(PlayerState.Active);
    }

    public void PlayTeleportStartSound()
    {
        _teleportStartSound?.Play();
    }

    public void PlayTeleportEndSound()
    {
        _teleportEndSound?.Play();
    }

    protected async Task TweenPlayer(CharacterBody2D player)
    {
        await player.TweenGlobalPosition(GlobalPosition + new Vector2(0, -4f), TeleportAnimationLength).PlayAsync(CancellationToken.None);

        // Create a Tween for the teleport animation
        // Tween tween = GetTree().CreateTween();
        // tween.SetEase(Tween.EaseType.InOut);
        // tween.SetTrans(Tween.TransitionType.Sine);
        // tween.TweenProperty(player, "global_position", GlobalPosition + new Vector2(0,-4f), TeleportAnimationLength);
        //
        // // Wait for the tween to finish
        // await ToSignal(tween, "finished");
    }
}