﻿using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using TMPro;
using UnityEngine;
using UnityEngine.Playables;

namespace CustomTimeline
{
    [ExecuteInEditMode]
    public class SlowMotionMixerBehaviour : PlayableBehaviour
    {
        TimelineSpeedController trackBinding;
        public Dictionary<string, double> markerClips;

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

            int inputCount = playable.GetInputCount();
            int totalInputWeight = 0;
            for (int i = 0; i < inputCount; i++)
            {
                float inputWeight = playable.GetInputWeight(i);
                ScriptPlayable<SlowMotionBehaviour> playableInput = (ScriptPlayable<SlowMotionBehaviour>)playable.GetInput(i);
                SlowMotionBehaviour input = playableInput.GetBehaviour();

                if (inputWeight > 0f)
                {
                    totalInputWeight++;

                    switch (input.action)
                    {
                        case SlowMotionBehaviour.SlowMotionAction.ContinuousSlowing:
                            {
                                if (input.event_Method.CheckCheckEventCondition())
                                    TimelineSpeedUp();
                                else
                                    TimelineSpeedDown(input);
                            }
                            break;
                        case SlowMotionBehaviour.SlowMotionAction.SlowDownAndJumpToMarker:
                            {
                                if (input.event_Method.CheckCheckEventCondition())
                                    JumpToEnd(playable, i);

                                TimelineSpeedDown(input);
                            }
                            break;
                        case SlowMotionBehaviour.SlowMotionAction.Marker:
                            {
                                TimelineSpeedUp();
                            }
                            break;
                    }
                }
            }

            if (totalInputWeight == 0)
                TimelineSpeedUp();

        }

        public void TimelineSpeedDown(SlowMotionBehaviour input)
        {
            if (trackBinding.speed > input.minTimelineSpeed + 0.001f)
            {
                trackBinding.speed = Mathf.Lerp(trackBinding.speed, input.minTimelineSpeed, input.lerpSpeed * Time.deltaTime);
            }
            else
            {
                trackBinding.speed = input.minTimelineSpeed;
            }
        }

        public void TimelineSpeedUp()
        {
            if (trackBinding.speed < 1 - 0.001f)
            {
                trackBinding.speed = Mathf.Lerp(trackBinding.speed, 1, 3 * Time.deltaTime);
            }
            else
            {
                trackBinding.speed = 1;
            }
        }

        public void JumpToEnd(Playable playable, int i)
        {
            float inputWeight = playable.GetInputWeight(i);
            ScriptPlayable<SlowMotionBehaviour> inputPlayable = (ScriptPlayable<SlowMotionBehaviour>)playable.GetInput(i);
            SlowMotionBehaviour input = inputPlayable.GetBehaviour();

            //Jump to marker
            double t = markerClips[input.markerToJumpTo];
            (playable.GetGraph().GetResolver() as PlayableDirector).time = t;
        }



        private void ResetTimelineSpeed()
        {
            if (!trackBinding)
                return;

            trackBinding.speed = 1.0f;
        }

        public override void OnBehaviourPause(Playable playable, FrameData info)
        {
            ResetTimelineSpeed();
        }

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

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