using TMPro;
using UnityEngine;
using UnityEngine.Playables;

namespace Streamingle.Subtitles
{
    public sealed class SubtitleMixerBehaviour : PlayableBehaviour
    {
        private const float MinimumWeight = 0.0001f;

        private TMP_Text trackBinding;
        private string appliedText;

        public override void ProcessFrame(Playable playable, FrameData info, object playerData)
        {
            SetBinding(playerData as TMP_Text);
            if (trackBinding == null)
                return;

            var selectedText = string.Empty;
            var greatestWeight = MinimumWeight;
            var inputCount = playable.GetInputCount();

            for (var index = 0; index < inputCount; index++)
            {
                var inputWeight = playable.GetInputWeight(index) * Mathf.Max(0f, info.effectiveWeight);
                if (inputWeight <= greatestWeight)
                    continue;

                var inputPlayable = (ScriptPlayable<SubtitleBehaviour>)playable.GetInput(index);
                selectedText = inputPlayable.GetBehaviour().Text ?? string.Empty;
                greatestWeight = inputWeight;
            }

            ApplyText(selectedText);
        }

        public override void OnGraphStop(Playable playable)
        {
            RestoreDefault();
        }

        public override void OnPlayableDestroy(Playable playable)
        {
            RestoreDefault();
        }

        private void SetBinding(TMP_Text target)
        {
            if (target == trackBinding)
                return;

            RestoreDefault();
            trackBinding = target;
            if (trackBinding == null)
                return;

            appliedText = null;
        }

        private void ApplyText(string value)
        {
            value ??= string.Empty;
            if (appliedText == value && trackBinding.text == value)
                return;

            trackBinding.text = value;
            appliedText = value;
        }

        private void RestoreDefault()
        {
            if (trackBinding == null)
                return;

            trackBinding.text = string.Empty;
            trackBinding = null;
            appliedText = null;
        }
    }
}
