using System;
using UnityEngine;

namespace mgaia.Utils.LayerSystem
{
    public class LayerSliceEffectRealMovement : LayerSliceEffect
    {
        public enum MovementTypes
        {
            ToRight,
            ToLeft,
            ToUp,
            ToDown
        }

        public MovementTypes MovementType;
        public bool Firula = false;

        [SerializeField]
        private float _timeToExecute = 0.75f;

        [SerializeField]
        private float _sharePositionModifier = 0.05f;

        [SerializeField]
        private float _shakeTimeModifier = 0.15f;

        private float mShakeTime;

        private bool mOriginalFirulaValue;
        private float mElapsedTime = 0.0f;
        private float mWidth, mHeight;
        private float mTargetTime;
        private Vector3 mInitialPosition, mFinalPosition, mFirulaPosition;
        private Vector3 mWidthIncVector, mHeightIncVector;

        protected override void CustomInit(bool removing)
        {
            mOriginalFirulaValue = Firula;

            Vector3 objectSize = transform.gameObject.GetSize(true, false);

            mWidth = objectSize.x;
            mWidthIncVector = new Vector3(1, 0, 0) * mWidth;
            mHeight = objectSize.y;
            mHeightIncVector = new Vector3(0, 1, 0) * mHeight;

            mShakeTime = _timeToExecute * _shakeTimeModifier;

            Firula = mOriginalFirulaValue;
            mElapsedTime = 0.0f;
            mTargetTime = _timeToExecute;
            float distance;
            mFinalPosition = mOriginalPosition;
            switch (MovementType)
            {
                case MovementTypes.ToLeft:
                    mInitialPosition = mOriginalPosition + mWidthIncVector;
                    distance = Mathf.Abs(mFinalPosition.x - mInitialPosition.x) * _sharePositionModifier;
                    mFirulaPosition = new Vector3(mFinalPosition.x - distance, mFinalPosition.y, mFinalPosition.z);
                    break;
                case MovementTypes.ToRight:
                    mInitialPosition = mOriginalPosition - mWidthIncVector;
                    distance = Mathf.Abs(mFinalPosition.x - mInitialPosition.x) * _sharePositionModifier;
                    mFirulaPosition = new Vector3(mFinalPosition.x + distance, mFinalPosition.y, mFinalPosition.z);
                    break;
                case MovementTypes.ToUp:
                    mInitialPosition = mOriginalPosition - mHeightIncVector;
                    distance = Mathf.Abs(mFinalPosition.y - mInitialPosition.y) * _sharePositionModifier;
                    mFirulaPosition = new Vector3(mFinalPosition.x, mFinalPosition.y + distance, mFinalPosition.z);
                    break;
                case MovementTypes.ToDown:
                    mInitialPosition = mOriginalPosition + mHeightIncVector;
                    distance = Mathf.Abs(mFinalPosition.y - mInitialPosition.y) * _sharePositionModifier;
                    mFirulaPosition = new Vector3(mFinalPosition.x, mFinalPosition.y - distance, mFinalPosition.z);
                    break;
                default:
                    Assert.AssertTrue(false, "Unimplemented movement transition type: " + MovementType.ToString());
                    break;
            }
            if (removing)
            {
                Vector3 temp = mInitialPosition;
                mInitialPosition = mFinalPosition;
                mFinalPosition = temp;
                Firula = false;
            }
            SetPosition(0.0f);
        }

        protected override bool CustomUpdate(float deltaTime)
        {
            mElapsedTime += deltaTime;
            if (mElapsedTime >= mTargetTime)
            {
                if (Firula)
                {
                    Firula = false;
                    mElapsedTime = 0.0f;
                    mTargetTime = mShakeTime;
                    mInitialPosition = mFirulaPosition;
                    return false;
                }
                else
                {
                    SetPosition(1.0f);
                    return true;
                }
            }
            else
            {
                float normalizedElapsedTime = mElapsedTime / mTargetTime;
                SetPosition(normalizedElapsedTime);
                return false;
            }
        }

        private void SetPosition(float normalizedElapsedTime)
        {
            if (Firula)
            {
                transform.position = Vector3.Lerp(mInitialPosition, mFirulaPosition, normalizedElapsedTime);
            }
            else
            {
                transform.position = Vector3.Lerp(mInitialPosition, mFinalPosition, normalizedElapsedTime);
            }
        }
    }
}