using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using RelicGGJ;

public class GridObject : MonoBehaviour {

    // Base class for any "interactable" (i.e. non-background) object on the grid.

    public gridLayer m_layer;
    public GridController m_level; // Reference to the grid
    public Vector2 m_position; // Grid x/y position of the object
    public Vector3 m_targetPosition;
    public objectType m_type; // Enum, how the object functions on collisions.
    public float m_movementPerSecond = 5f;

    // Enum for object type
    public enum objectType
    {
        STATIC,
        PLAYER,
        ENEMY,
        COLLECTABLE,
        EXIT_UP,
        EXIT_DOWN,
        GOAL
    }

    protected virtual void Update ()
    {
        if (transform.position != m_targetPosition && m_targetPosition != Vector3.zero)
        {
            if (Vector3.SqrMagnitude(transform.position - m_targetPosition) < 0.001f)
            {
                transform.position = m_targetPosition;
            }
            else
            {
                transform.position = Vector3.Lerp(transform.position, m_targetPosition, Time.deltaTime * m_movementPerSecond);
            }
        }
    }

    // Overridable initialization function
    virtual public void Init (gridLayer layer)
    {
        // At the very least, initialize the grid reference
        GridController gridController = GameManager.Instance.m_currentLevel;
        if (gridController != null)
        {
            m_level = gridController;
        }
        m_layer = layer;
    }

    // What to do on each game update.
    virtual public void GameTick()
    {
        // Do nothing.
    }

    // This can optionally be overriden: What to do when something tries to move into this object.
    virtual public void Push(GridObject source)
    {
        // If not overriden, do nothing. (Walls use this.)
    }

    // Given a target position, attempt to move there.
    // This takes a Vector2, but if you try to use floats, you're going to have a bad time.
    public void Move(ref Vector2 newPos)
    {
        // Check if the position is valid given the grid's extents.
        if (m_level.CheckValidPosition(newPos.x, newPos.y))
        {
            GameObject found = m_level.GetObjectAt(newPos.x, newPos.y);
            if (found != null)
            {
                //Debug.Log(found.name);
                GridObject gObj = found.GetComponent<GridObject>();
                if (gObj != null)
                {
                    switch (gObj.m_layer)
                    {
                        case gridLayer.BACKGROUND:
                            m_level.SetObjectAt(m_position.x, m_position.y, null, m_layer);
                            m_position = newPos;
                            m_level.SetObjectAt(m_position.x, m_position.y, gameObject, m_layer);
                            break;
                        default:
                            gObj.Push(this);
                            break;
                    }
                }
            }
        }
    }

    // This is done every game update: given the grid coordinates of the object,
    // update the Unity GameObject's position.
    public void UpdatePosition()
    {
        if (m_level != null)
        {
            float newX, newY;
            newX = m_position.x + 1f - (m_level.m_width / 2f);
            newY = -1f - m_position.y + (m_level.m_height / 2f);
            m_targetPosition = new Vector3(newX, newY, transform.position.z);
        }
    }
}
