using Godot;
using Godot.Collections;

public partial class AudioSequencer : Node
{
	private static AudioSequencer instance;
	[Export]private Dictionary<string, AudioStreamPlayer> channels = [];
	[Export]private Dictionary<string, bool> channelProcess = [];
	[Export]private Dictionary<string, ChannelSettings> channelSettings = [];

	[Export]
	private ChannelSettings standardSettings;

	public override void _Ready()
	{
		instance = this;
	}

	public static bool IsChannelPlaying(string id)
	{
		if (instance.channels.ContainsKey(id) == false)
		{
			instance.InitiateChannel(id);
			return false;
		}

		if (instance.channelSettings[id].restartTreshold == 0)
			return false;
		if (instance.channelSettings[id].restartTreshold < 0)
			return instance.channelProcess[id];

		return instance.channelProcess[id] && instance.channels[id].GetPlaybackPosition() < instance.channelSettings[id].restartTreshold / Engine.TimeScale;
	}

	public static void Play(string id, AudioStream what, ChannelSettings settings = null)
	{
		if (IsChannelPlaying(id)) return;
		if (settings != null) ChangeSettings(id, settings);
		instance.PlayAtChannel(id, what);
	}

	public static void ChangeSettings(string id, ChannelSettings settings)
	{
		
		if (instance.channels.ContainsKey(id) == false)
			{
				instance.InitiateChannel(id, settings);
				return;
			}
		if (settings == null)
		{
			instance.channelSettings[id] = instance.standardSettings;
			return;
		}
		instance.channelSettings[id] = settings;
	}

	private AudioStreamPlayer InitiateChannel(string id, ChannelSettings settings = null)
	{
		AudioStreamPlayer player = new();

		AddChild(player);
		channels.Add(id, player);
		channelProcess.Add(id, false);
		player.Name = id;
		player.MaxPolyphony = 5;
		player.Bus = "SFXBus";

		player.Finished += () => { MarkChannel(id, false); };

		if (settings != null)
		{
			channelSettings.Add(id, settings);
		}
		else
		{
			channelSettings.Add(id, standardSettings);
		}

		return player;
	}

	private void PlayAtChannel(string id, AudioStream what)
	{
		channels[id].Stream = what;
		channels[id].Play();
		MarkChannel(id, true);
	}

	private void MarkChannel(string id, bool how)
	{
		channelProcess[id] = how;
	}
}
