﻿using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using Arugula;
using Arugula.Animation;
using Arugula.Audio;

namespace Arugula.Prototypical
{
    public class RichLabel : MonoBehaviour
    {
        [System.Serializable]
        public class Transition
        {
            public Tween.Options options;
            public TransformPose pose;
            public Color color;
            public Phonic.Options soundOptions;
            [PhonicSound] public string sound;

            ITween<TransformPose> poseTween;
            ITween<Color> colorTween;
            bool busy;

            public void Apply(Transform t, TMP_Text tmp)
            {
                pose.Apply(t);
                tmp.color = color;
            }

            public void Start(Transform t, TMP_Text tmp)
            {
                if (busy)
                    return;

                poseTween = t.PoseTo(pose, options);
                poseTween.OnFinished += (x) => busy = false;
                colorTween = tmp.color.FadeTo(color, options, context: tmp);
                colorTween.OnUpdatedValue += (x) => tmp.color = x;
                soundOptions.position = t.position;
                Phonic.Play(sound, soundOptions);
                busy = true;
            }

            public void Stop()
            {
                if (poseTween != null && !poseTween.Finished) poseTween.Finish(false);
                if (colorTween != null && !colorTween.Finished) colorTween.Finish(false);
            }
        }

        [SerializeField] private TMP_Text textMesh;
        [SerializeField] private string _text;
        public string text
        {
            get => _text;
            set
            {
                _text = value;
                textMesh.text = openTags + text + closeTags;
            }
        }
        public string openTags;
        public string closeTags;

        [Header("Show")]
        public Transition showTransition;

        [Header("Hide")]
        public Transition hideTransition;

        [Header("Automation")]
        public bool showOnStart = false;
        public Collider trigger;
        public LayerMask triggerMask = 0;
        public string triggerTag = "";
        public bool showWhileTriggerStay;
        [Min(0)]
        public float autoHideTimeout = 2.5f;


        public event System.Action<RichLabel> OnShow = delegate { };
        public event System.Action<RichLabel> OnHide = delegate { };

        Tween tween;
        bool showing = false;
        float showTimeout = -1;

        private void Start()
        {
            ApplyTags();

            hideTransition.Apply(transform, textMesh);
            if (showOnStart)
                Show();
        }

        private void OnEnable()
        {
            if (trigger != null)
            {
                if (showWhileTriggerStay)
                {
                    TriggerListener.Register(trigger, HandleTriggerCallback, HandleTriggerCallback);
                }
                else
                {
                    TriggerListener.Register(trigger, HandleTriggerCallback);
                }
            }
        }

        private void OnDisable()
        {
            if (trigger != null)
                TriggerListener.Unregister(trigger.gameObject, HandleTriggerCallback, HandleTriggerCallback);
        }

        private void HandleTriggerCallback(Collider collider)
        {
            if (triggerMask.Contains(collider.gameObject.layer))
            {
                if (triggerTag != null && triggerTag != "")
                {
                    if (collider.gameObject.CompareTag(triggerTag))
                        Show();
                }
                else
                {
                    Show();
                }
            }
        }

        [ContextMenu("Apply Tags")]
        public void ApplyTags()
        {
            text = _text;
        }


        private void Update()
        {
            if (showing && showTimeout > 0)
            {
                if (Time.unscaledTime > showTimeout)
                {
                    Hide();
                }
            }
        }

        public void Show()
        {

            if (autoHideTimeout > 0)
                showTimeout = Time.unscaledTime + autoHideTimeout;
            else
                showTimeout = float.MaxValue;

            if (!showing)
            {
                hideTransition.Stop();
                showTransition.Start(transform, textMesh);
                OnShow(this);
            }

            showing = true;
        }

        public void Hide()
        {
            if (showing)
            {
                showTransition.Stop();
                hideTransition.Start(transform, textMesh);
                OnHide(this);
            }


            showing = false;
        }
    }
}