using System;
using System.Collections.Generic;
using UnityEngine;
using ScrambleKit.Move;

namespace ScrambleKit.Experimental.Carry
{
    [RequireComponent(typeof(MoveCore))]
    public class Carrier : MonoBehaviour
    {
        public Vector2 PickupAreaFrom;
        public Vector2 PickupAreaTo;
        public Vector2 CarryingLocation = Vector2.up;
        public LayerMask PickupLayers = ~0;  // ~0 means "all layers"
        public float ThrowSpeed = 10f;

        private Rigidbody2D rb;
        private Transform carrying;
        private Rigidbody2D carryrb;
        private Collider2D carrycol;

        private MoveCore core;
        private const string CARRY = "Carry";

        void FixedUpdate()
        {
            if (core.input.ConsumeTrigger(CARRY))
            {
                if (carrying == null)
                    TryPickup();
                else
                    Throw();
            }
        }

        private void TryPickup()
        {
            Transform t = GetCarriableInRange();
            if (t == null)
                return;
            Carry(t);
        }

        private Transform GetCarriableInRange()
        {
            Vector2 pos = transform.position;
            Collider2D[] cols = Physics2D.OverlapAreaAll(pos + PickupAreaFrom, pos + PickupAreaTo, PickupLayers);
            foreach(Collider2D col in cols)
            {
                Carryable carry = col.transform.GetComponent<Carryable>();
                if (carry != null)
                    return col.transform;
            }

            return null;
        }

        private void Carry(Transform t)
        {
            carrying = t;
            carryrb = carrying.GetComponent<Rigidbody2D>();
            carrycol = carrying.GetComponent<Collider2D>();

            carrying.SetParent(transform);
            carrying.localPosition = CarryingLocation;
            carryrb.isKinematic = true;
            carryrb.velocity = Vector2.zero;
            carrycol.enabled = false;
        }

        private void Throw()
        {
            // EXPERIMENTAL:  TODO Remove
           carryrb.constraints = carryrb.constraints & ~RigidbodyConstraints2D.FreezePositionX;
            //

            carrying.parent = null;
            carryrb.isKinematic = false;
            carrycol.enabled = true;

            ApplyThrowForce();

            carrying = null;
            carryrb = null;
            carrycol = null;

            
        }

        private void ApplyThrowForce()
        {
            Vector2 accel = core.rb2.velocity + ThrowSpeed * ((Vector2)transform.right*Math.Sign(transform.localScale.x) + Vector2.up).normalized;
            Vector2 force = accel * carryrb.mass;
            //carryrb.AddForce(force, ForceMode2D.Impulse);
            carryrb.velocity = accel;
        }

        void AddBindingNames(HashSet<string> bindingNames)
        {
            bindingNames.Add(CARRY);
        }

        void Start()
        {
            core = GetComponent<MoveCore>();
        }
    }
}