using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using UnityEngine.UI;
using UnityEngine.Video;

namespace SimplifyXR
{

    public enum VideoPanelState
    {
        Paused,
        Playing,         
        Finished
    }

    [System.Serializable]
    public class VideoPanelProps {
        public string videoTitle;
        public VideoSource source;
        [Conditional("source", VideoSource.Url, ComparisonType.Equals)]
        public string URL;
        [Conditional("source", VideoSource.VideoClip,ComparisonType.Equals)]
        public VideoClip videoClip;
        public bool playAutomatically = true;
        public bool scalePanelToVideoAspect = true;
    }

    public class VideoPanelFeatures : BasePanelFeatures
    {

        [Header("Video Panel Features")]
        [Tooltip("Customize the behavior of the Standard Video Panel features")]
        public bool customizeVideoFeatures = true;
        [Conditional("customizeVideoFeatures", true, ComparisonType.Equals),
            Tooltip("Auto configure the video player play, pause and rewind controls.")]
        public bool autoPlayerControls = true;
        [Conditional("customizeVideoFeatures", true, ComparisonType.Equals),
            Tooltip("Auto configure the video scrubbing, using the slider to seek to a playback time of the video")]
        public bool autoScrub = true;


        public TextMeshProUGUI startTimeText => baseRoot.GetElementAsType<TextMeshProUGUI>("Video Start Time");
        public TextMeshProUGUI endTimeText => baseRoot.GetElementAsType<TextMeshProUGUI>("Video End Time");
        public Slider scrubSlider => baseRoot.GetElementAsType<Slider>("Video Slider");
        public VideoPlayer videoPlayer => baseRoot.GetElementAsType<VideoPlayer>("Video Content");
        public Button actionButton => baseRoot.GetElementAsType<Button>("Action Button");
        public ActionButton actionController => baseRoot.GetElementAsType<ActionButton>("Action Controller");

        Coroutine updateVideoRoutine;
        VideoPanelState state;
        bool aspectUpdated;
        VideoPanelProps activeProps;


        private void InitializePlayer()
        {
            aspectUpdated = false;
            startTimeText.text = "0:00";
            actionController.UpdateIconByState(state);
            scrubSlider.SetValueWithoutNotify(0);
        }


        public void UpdateVideoAspect(VideoPlayer player)
        {

            var tex = player.texture;
            var aspect = (float)tex.width /
                     ((float)tex.height);


            var aspectFitter = player.GetComponentInChildren<AspectRatioFitter>();
            if (aspectFitter != null)
            {
                aspectFitter.aspectRatio = aspect;
            }

            if ( activeProps != null && 
                activeProps.scalePanelToVideoAspect)
            {
                var panelRect = baseRoot.GetComponent<RectTransform>();
                panelRect.sizeDelta = new Vector2(
                    panelRect.sizeDelta.y * (aspect * 0.77f),
                    panelRect.sizeDelta.y
                    );
            }
            aspectUpdated = true;


        }

        private void HandleButtonActionByState()
        {
            switch (state)
            {
                case VideoPanelState.Paused:
                    PlayVideo();
                    break;
                case VideoPanelState.Playing:
                    PauseVideo();
                    break;
                case VideoPanelState.Finished:
                    RestartVideo();
                    break;
            }

            actionController.UpdateIconByState(state);
        }


        private void UpdateData()
        {
            endTimeText.text = ConvertTimeCodeToTime(videoPlayer.length);
            startTimeText.text = ConvertTimeCodeToTime(videoPlayer.time);
            if (videoPlayer.isPrepared) scrubSlider.SetValueWithoutNotify((float)(videoPlayer.time / videoPlayer.length));
            if (videoPlayer.isPrepared && !aspectUpdated) UpdateVideoAspect(videoPlayer);
        }

        private IEnumerator UpdateRoutine()
        {
            while (true)
            {
                yield return new WaitForSeconds(1f);
                UpdateData();
            }
        }

        private void ScrubToTimeCode(float value)
        {
            videoPlayer.time = ConvertSliderValueToTimeCode(value);

            if (state.Equals(VideoPanelState.Finished)
                && videoPlayer.time != videoPlayer.length)
            {
                PauseVideo();
                videoPlayer.time = ConvertSliderValueToTimeCode(value);
                actionController.UpdateIconByState(state);
            }
        }

        private double ConvertSliderValueToTimeCode(float value)
        {
            var timeValue = value / 1.0f;
            var convertedTime = videoPlayer.length * timeValue;
            return convertedTime;
        }

        private void HandleEndReached(VideoPlayer source)
        {
            state = VideoPanelState.Finished;
            actionController.UpdateIconByState(state);
        }

        private void RestartVideo()
        {
            videoPlayer.time = 0;
            PlayVideo();
        }

        private void PauseVideo()
        {
            videoPlayer.Pause();
            state = VideoPanelState.Paused;
            StopCoroutine(updateVideoRoutine);
        }

        private void PlayVideo()
        {
            videoPlayer.Play();
            state = VideoPanelState.Playing;
            if (updateVideoRoutine != null) StopCoroutine(updateVideoRoutine);
            updateVideoRoutine = StartCoroutine(UpdateRoutine());
        }

        private string ConvertTimeCodeToTime(double timeCode)
        {
            var minutes = Mathf.RoundToInt( (float)timeCode / 60f);
            var seconds = (int) (timeCode % 60);
            string secondString = seconds < 10 ?
                "0" + seconds : seconds.ToString();

            return minutes + ":" + secondString;

        }


        public void SetVideo(VideoPanelProps panelProps)
        {
            activeProps = panelProps;
            titleText.text = panelProps.videoTitle;
            videoPlayer.source = panelProps.source;
            videoPlayer.url = panelProps.source == VideoSource.Url ? 
                panelProps.URL : null;
            videoPlayer.clip = panelProps.source == VideoSource.VideoClip ? 
                panelProps.videoClip : null;

            if (panelProps.playAutomatically)
            {
                PlayVideo();
            }
            else
            {
                PauseVideo();
            }

            InitializePlayer();
        }


        public new void Awake()
        {
            base.Awake();

            if(autoScrub) scrubSlider.onValueChanged.AddListener(ScrubToTimeCode);
            if(autoPlayerControls) actionButton.onClick.AddListener(HandleButtonActionByState);

            if (autoPlayerControls) videoPlayer.loopPointReached -= HandleEndReached;
            if (autoPlayerControls) videoPlayer.loopPointReached += HandleEndReached;

        }

        private void TestVideo()
        {

            PlayVideo();
            InitializePlayer();
        }

        public new void OnDestroy()
        {
            base.OnDestroy();

            if (autoScrub) scrubSlider.onValueChanged.RemoveAllListeners();
            if (autoPlayerControls) actionButton.onClick.RemoveListener(HandleButtonActionByState);

            if (autoPlayerControls) videoPlayer.loopPointReached -= HandleEndReached;
        }


    }



}

