using System;
using UnityEngine;

namespace ScrambleKit.Experimental.SnappyBlocks
{
    public class AlignToInterval : MonoBehaviour
    {

        public Vector2 Interval = Vector2.one;
        public float ActivateBelowSpeed = 3f;
        public string DEBUG;

        private Rigidbody2D rb2;

        private bool snapped;

        void FixedUpdate()
        {
            if (transform.parent != null)
                return;

            if ((rb2.constraints & RigidbodyConstraints2D.FreezePositionX) == 0) // !rb2.isKinematic)
                snapped = false;

            if(!snapped && !MovingTooFast())
            {
                Snap();
            }
        }

        private bool MovingTooFast()
        {
            return rb2.velocity.magnitude >= ActivateBelowSpeed;
        }

        private void Snap()
        {
            snapped = true;
            rb2.velocity = Vector2.zero;
            //rb2.isKinematic = true;
            rb2.constraints = RigidbodyConstraints2D.FreezePositionX | RigidbodyConstraints2D.FreezeRotation;
            Debug.Log("Moved " + name + " from " + transform.position + " snap to " + GetNearestSnapPoint());
            transform.position = GetNearestSnapPoint();
        }

        private Vector3 GetNearestSnapPoint()
        {
            float xoffset = PositiveMod(transform.position.x, Interval.x);
            float yoffset = PositiveMod(transform.position.y, Interval.y);

            float xmove = GetMoveToNearestInterval(xoffset, Interval.x);
            float ymove = GetMoveToNearestInterval(yoffset, Interval.y);
            Debug.Log("Getting snap point: offset " + xoffset + ", " + yoffset + ", moves " + xmove + ", " + ymove);
            DEBUG = "x " + xmove + ", y " + ymove; //"x " + xoffset + ", y " + yoffset;

            return transform.position + new Vector3(xmove, ymove, 0);
        }

        private float PositiveMod(float val, float interval)
        {
            // modulus has tricky treatment of negative numbers: -1.2 % 1 is -0.2 and we need to convert it to 0.8
            float mod = val % interval;
            if (mod < 0)
                mod = interval + mod;
            return mod;
        }

        private float GetMoveToNearestInterval(float offset, float interval)
        {
            float move;
            if (offset >= interval/2)
                move = interval - offset;
            else
                move = -offset;
            return move;
        }

        void Start()
        {
            rb2 = GetComponent<Rigidbody2D>();
        }
        
    }
}