
using System;

namespace Animrig
{
    public class SpineRenderer : StateRenderer
    {
        // property
        public static readonly int SaveVersion = 1; 
        public Spine.AnimationState state = null;
        public Spine.Skeleton skeleton = null;
        // public
        public SpineRenderer()
        {
            ObjectType = ObjectType.Spine;
        }
        // common 
        public override void Update(double deltatime)
        {
            if (state == null) return;
            if (skeleton == null) return;

            state.Update((float)deltatime);
            state.Apply(skeleton);
            skeleton.UpdateWorldTransform();
        }
        // spine
        public override void SetAnimation(int trackindex, int usetrack, string basename, bool loop, bool addanim, MixBlend trackmix, float duration, bool seekmode)
        {
            void inSetEmpty(int index)
            {
                float d = state.Data.DefaultMix;
                if (duration >= 0.0) d = duration; 

                if (addanim)
                    state.AddEmptyAnimation(index, d, 0.0f);
                else
                    state.SetEmptyAnimation(index, d);
            }
            void inSetAnimation(int index, string name1, string name2)
            {
                // search
                var anim = state.Data.SkeletonData.FindAnimation(name1);
                if (anim == null) anim = state.Data.SkeletonData.FindAnimation(name2);

                if (anim == null)
                {
                    inSetEmpty(index);
                }
                else
                {
                    // set animation
                    Spine.TrackEntry track;
                    if (addanim)
                        track = state.AddAnimation(index, anim, loop, 0.0f);
                    else
                        track = state.SetAnimation(index, anim, loop);
                    if (track != null)
                    {
                        // mix blend
                        if ((track.MixBlend == Spine.MixBlend.Replace)||(track.MixBlend == Spine.MixBlend.Add))     // safe code
                        {
                            switch (trackmix)
                            {
                                case MixBlend.Add:
                                    track.MixBlend = Spine.MixBlend.Add;
                                    break;
                                case MixBlend.Replace:
                                    track.MixBlend = Spine.MixBlend.Replace;
                                    break;
                            }
                        }
                        // duration
                        if (duration < 0.0f)
                        {
                            // use default duration
                        }
                        else
                        {
                            track.MixDuration = Math.Max(duration, 0.0f);
                        }
                        // seek mode
                        if (seekmode)
                            track.TimeScale = 0.0f;
                        else
                            track.TimeScale = 1.0f;
                    }
                }
            }

            if (state == null) return;
            
            // layertype AnimBlend1
            if (usetrack == 1)
            {
                if (basename == "empty")
                {
                    inSetEmpty(trackindex + 0);
                }
                else
                {
                    inSetAnimation(trackindex + 0, basename, basename + "@up");
                }
                return;
            }
            
            // layertype AnimBlend4
            if (usetrack == 4)
            {
                if (basename == "empty")
                {
                    inSetEmpty(trackindex + 0);
                    inSetEmpty(trackindex + 1);
                    inSetEmpty(trackindex + 2);
                    inSetEmpty(trackindex + 3);
                }
                else
                {
                    inSetAnimation(trackindex + 0, basename, basename + "@up");
                    inSetAnimation(trackindex + 1, basename + "@right", "");
                    inSetAnimation(trackindex + 2, basename + "@down", "");
                    inSetAnimation(trackindex + 3, basename + "@left", "");

                }
            }
        }
        public override void SetTrackBlendAlpha(int trackindex, int usetrack, float alpha1, float alpha2, float alpha3, float alpha4, bool exists)
        {
            void inSet(int index, float alpha)
            {
                var track = state.GetCurrent(index);
                if (track == null) return;

                track.Alpha = alpha;
            }

            if (state == null) return;

            if (usetrack == 1)
            {
                inSet(trackindex + 0, alpha1);
            }
            else
            {
                inSet(trackindex + 0, alpha1);
                inSet(trackindex + 1, alpha2);
                inSet(trackindex + 2, alpha3);
                inSet(trackindex + 3, alpha4);
            }
        }
        public override void SetTrackSeekTime(int trackindex, int usetrack, float time1, float time2, float time3, float time4, bool exists)
        {
            void inSet(int index, float time)
            {
                var track = state.GetCurrent(index);
                if (track == null) return;

                track.TrackTime = time;
            }

            if (state == null) return;

            if (usetrack == 1)
            {
                inSet(trackindex + 0, time1);
            }
            else
            {
                inSet(trackindex + 0, time1);
                inSet(trackindex + 1, time2);
                inSet(trackindex + 2, time3);
                inSet(trackindex + 3, time4);
            }
        }
        public override void SetMixDuration(float duration)
        {
            if (state == null) return;

            state.Data.DefaultMix = duration;
        }
    }
}