﻿using RimWorld;
using rjw;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using UnityEngine;
using Verse;

namespace Rimworld_Animations {
    public class CompThingAnimator : ThingComp
    {
        Vector3 anchor;

        Pawn pawn;

        public bool isAnimating = false, mirror;

        int animTicks = 0, stageTicks = 0, clipTicks = 0, curStage = 0;
        float rotation = 0;
        float clipPercent = 0;

        public Vector3 deltaPos;

        AnimationDef anim;
        private ThingAnimationClip clip => (ThingAnimationClip)stage.animationClips[1];
        private AnimationStage stage
        {
            get
            {
                return anim.animationStages[curStage];
            }

        }

        public void StartAnimation(AnimationDef anim, Pawn pawn, bool mirror = false)
        {
            isAnimating = true;

            this.anim = anim;
            this.pawn = pawn;
            this.mirror = mirror;

            animTicks = 0;
            stageTicks = 0;
            clipTicks = 0;

            curStage = 0;
            clipPercent = 0;

            tickAnim();

        }

        public void setAnchor(IntVec3 position)
        {
            anchor = position.ToVector3();
        }

        public override void CompTick()
        {
            base.CompTick();

            if(isAnimating)
            {
                if (pawn.Dead || pawn?.jobs?.curDriver == null || (pawn?.jobs?.curDriver != null && !(pawn?.jobs?.curDriver is rjw.JobDriver_Sex)))
                {
                    isAnimating = false;
                }
                else
                {
                    tickAnim();
                }
            }

            
        }

        public void tickAnim()
        {
            if (!isAnimating) return;
            animTicks++;

            if (animTicks < anim.animationTimeTicks)
            {
                tickStage();
            }
            else
            {
                if (LoopNeverending())
                {
                    ResetOnLoop();
                }
                else
                {
                    isAnimating = false;
                }


            }

        }

        public void tickStage()
        {
            if (stage == null)
            {
                isAnimating = false;
                return;
            }

            stageTicks++;

            if (stageTicks >= stage.playTimeTicks)
            {

                curStage++;

                stageTicks = 0;
                clipTicks = 0;
                clipPercent = 0;
            }

            if (curStage >= anim.animationStages.Count)
            {
                if (LoopNeverending())
                {
                    ResetOnLoop();
                }
                else
                {
                    isAnimating = false;
                }

            }
            else
            {
                tickClip();
            }
        }

        public void tickClip()
        {
            clipTicks++;

            if (clipPercent >= 1 && stage.isLooping)
            {
                clipTicks = 1;//warning: don't set to zero or else calculations go wrong
            }
            clipPercent = (float)clipTicks / (float)clip.duration;

            calculateDrawValues();
        }

        public void setAnchor(Thing thing)
        {

            //center on bed
            if (thing is Building_Bed)
            {
                anchor = thing.Position.ToVector3();
                if (((Building_Bed)thing).SleepingSlotsCount == 2)
                {
                    if (thing.Rotation.AsInt == 0)
                    {
                        anchor.x += 1;
                        anchor.z += 1;
                    }
                    else if (thing.Rotation.AsInt == 1)
                    {
                        anchor.x += 1;
                    }
                    else if (thing.Rotation.AsInt == 3)
                    {
                        anchor.z += 1;
                    }

                }
                else
                {
                    if (thing.Rotation.AsInt == 0)
                    {
                        anchor.x += 0.5f;
                        anchor.z += 1f;
                    }
                    else if (thing.Rotation.AsInt == 1)
                    {
                        anchor.x += 1f;
                        anchor.z += 0.5f;
                    }
                    else if (thing.Rotation.AsInt == 2)
                    {
                        anchor.x += 0.5f;
                    }
                    else
                    {
                        anchor.z += 0.5f;
                    }
                }
            }
            else
            {
                anchor = thing.Position.ToVector3Shifted();
            }

            anchor -= new Vector3(0.5f, 0, 0.5f);
        }
        private void calculateDrawValues()
        {
            
            //shift up and right 0.5f to align center
            deltaPos = new Vector3((clip.PositionX.Evaluate(clipPercent)) * (mirror ? -1 : 1) + 0.5f, AltitudeLayer.Item.AltitudeFor(), clip.PositionZ.Evaluate(clipPercent) + 0.5f);
            //Log.Message("Clip percent: " + clipPercent + " deltaPos: " + deltaPos);
            rotation = clip.Rotation.Evaluate(clipPercent) * (mirror ? -1 : 1);
        }

        public void AnimateThing(Thing thing) 
        {
            thing.Graphic.Draw(deltaPos + anchor, mirror ? Rot4.West : Rot4.East, thing, rotation);
        }

        public bool LoopNeverending()
        {
            if (pawn?.jobs?.curDriver != null &&
                (pawn.jobs.curDriver is JobDriver_Sex) && (pawn.jobs.curDriver as JobDriver_Sex).neverendingsex)
            {
                return true;
            }

            return false;
        }

        public void ResetOnLoop()
        {
            curStage = 1;
            animTicks = 0;
            stageTicks = 0;
            clipTicks = 0;

            tickAnim();
        }

    }
}
