using UnityEngine;
using System.Collections;

public class Block: MonoBehaviour 
{
    [SerializeField]
    private float friction = 3.0f;

    [SerializeField]
    private float lockSpeed = 0.2f;

    [SerializeField]
    private float unlockSpeed = 0.1f;

    private float staticTimeLeft = 0.0f;

    [SerializeField]
    private float blockOnBlockActionThreshold = 0.1f;

    [SerializeField]
    private float blockOnBlockActionKinematicDuration = 0.2f;

    void OnCollision(Collision collision)
    {
        if (collision.rigidbody != null && collision.rigidbody.GetComponent<Block>() != null)
        {
            if (Mathf.Abs(Vector3.Dot(collision.relativeVelocity, collision.contacts[0].normal)) > blockOnBlockActionThreshold || Mathf.Abs(Vector3.Dot(rigidbody.velocity, collision.contacts[0].normal)) > blockOnBlockActionThreshold)
            {
                rigidbody.isKinematic = true;
                staticTimeLeft = blockOnBlockActionKinematicDuration;
            }
        }
    }

    void OnCollisionStay(Collision collision)
    {
        OnCollision(collision);
    }

    void OnCollisionEnter(Collision collision)
    {
        OnCollision(collision);
    }

    void Start()
    {
        staticTimeLeft = -1000.0f;
    }

	void FixedUpdate()
    {
        RigidbodyConstraints constraints = rigidbody.constraints;

        bool lockedToX = ((constraints & RigidbodyConstraints.FreezePositionY) == RigidbodyConstraints.FreezePositionY);
        bool lockedToY = ((constraints & RigidbodyConstraints.FreezePositionX) == RigidbodyConstraints.FreezePositionX);

        if (lockedToX && rigidbody.velocity.x < unlockSpeed)
        {
            lockedToX = false;
            constraints &= ~RigidbodyConstraints.FreezePositionY;
        }
        else if (lockedToY && rigidbody.velocity.y < unlockSpeed)
        {
            lockedToY = false;
            constraints &= ~RigidbodyConstraints.FreezePositionX;
        }
        else
        {
            if (rigidbody.velocity.x > lockSpeed)
            {
                lockedToX = true;
                constraints |= RigidbodyConstraints.FreezePositionY;
            }
            else if (rigidbody.velocity.y > lockSpeed)
            {
                lockedToY = true;
                constraints |= RigidbodyConstraints.FreezePositionX;
            }
        }

        rigidbody.constraints = constraints;

        rigidbody.AddForce(-Vector3.ClampMagnitude(rigidbody.velocity, friction * Time.fixedDeltaTime), ForceMode.VelocityChange);

        staticTimeLeft -= Time.fixedDeltaTime;
        if (staticTimeLeft < 0.0f)
        {
            rigidbody.isKinematic = false;
        }
        else
        {
            rigidbody.isKinematic = true;
        }
        rigidbody.mass = Mathf.Lerp(1000.0f, 1.0f, Mathf.InverseLerp(0.0f, -0.2f, staticTimeLeft));
    }
}
