using System;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;

public class TetraManager : MonoBehaviour
{
    public GameObject[] TetraPrefabs;
    private float m_speed = 4f;
    private float _gridSize = 1f;

    private float _gridLeftBound = -4f;
    private float _gridRightBound = 4f;
    private float _gridBottomBound = -9f;
    private float _gridTopBound = 10f;

    private List<GameObject> _placedTetras = new List<GameObject>();
    private GameObject _activeTetra;
    private float _moveTimer;

    void Start()
    {
        SpawnTetra();
        _moveTimer = 0f;
    }

    void Update()
    {
        if (_activeTetra != null)
        {
            _moveTimer += Time.deltaTime;

            if (_moveTimer >= 1f / m_speed)
            {
                MoveTetraDown();
                _moveTimer = 0f;
            }

            if (Input.GetKeyDown(KeyCode.A) || Input.GetKeyDown(KeyCode.LeftArrow))
            {
                MoveLeft();
            }

            if (Input.GetKeyDown(KeyCode.D) || Input.GetKeyDown(KeyCode.RightArrow))
            {
                MoveRight();
            }
        }
    }

    void MoveTetraDown()
    {
        if (_activeTetra == null) return;

        Vector3 newPosition = _activeTetra.transform.position;
        newPosition.y -= _gridSize;

        if (IsValidMove(newPosition))
        {
            _activeTetra.transform.position = newPosition;
        }
        else
        {
            PlaceTetra();
            SpawnTetra();
        }
    }

    void SpawnTetra()
    {
        if (TetraPrefabs.Length == 0)
        {
            Debug.LogError("No tetra prefabs defined in the array.");
            return;
        }

        int randomIndex = Random.Range(0, TetraPrefabs.Length);
        GameObject tetraPrefab = TetraPrefabs[randomIndex];

        Vector3 spawnPosition = new Vector3(
            Mathf.Round(transform.position.x / _gridSize) * _gridSize,
            Mathf.Round(transform.position.y / _gridSize) * _gridSize,
            0);

        Renderer prefabRenderer = tetraPrefab.GetComponent<Renderer>();
        if (prefabRenderer != null)
        {
            float tetraHeight = prefabRenderer.bounds.size.y;

            switch (randomIndex)
            {
                case 0:
                    _gridRightBound = 5f;
                    spawnPosition.y -= tetraHeight / 3.9f;
                    break;
                case 1:
                case 2:
                case 4:
                    _gridRightBound = 4f;
                    spawnPosition.y -= tetraHeight / 5.5f;
                    break;
                case 3:
                    _gridRightBound = 4f;
                    spawnPosition.y -= Mathf.Round(tetraHeight / 4f);
                    break;
            }
        }

        _activeTetra = Instantiate(tetraPrefab, spawnPosition, Quaternion.identity);
    }

    void MoveLeft()
    {
        if (_activeTetra == null) return;

        Vector3 newPosition = _activeTetra.transform.position;
        newPosition.x -= _gridSize;

        if (IsValidMove(newPosition))
        {
            _activeTetra.transform.position = newPosition;
        }
    }

    void MoveRight()
    {
        if (_activeTetra == null) return;

        Vector3 newPosition = _activeTetra.transform.position;
        newPosition.x += _gridSize;

        if (IsValidMove(newPosition))
        {
            _activeTetra.transform.position = newPosition;
        }
    }

    bool IsValidMove(Vector3 position)
    {
        return IsWithinGrid(position) && !IsColliding(position);
    }

    bool IsWithinGrid(Vector3 position)
    {
        return position.x >= _gridLeftBound && position.x <= _gridRightBound &&
               position.y >= _gridBottomBound && position.y <= _gridTopBound;
    }

    bool IsColliding(Vector3 position)
    {
        Bounds activeBounds = GetTetraBounds(_activeTetra, position);

        foreach (GameObject placedTetra in _placedTetras)
        {
            Bounds placedBounds = GetTetraBounds(placedTetra, placedTetra.transform.position);

            if (activeBounds.Intersects(placedBounds))
            {
                return true;
            }
        }

        return false;
    }

    Bounds GetTetraBounds(GameObject tetra, Vector3 position)
    {
        Collider Collider = tetra.GetComponent<Collider>();
        if (Collider != null)
        {
            Bounds bounds = Collider.bounds;
            bounds.center = position;
            return bounds;
        }

        return new Bounds(Collider.bounds);
    }

    void PlaceTetra()
    {
        if (_activeTetra != null)
        { 
            _placedTetras.Add(_activeTetra);
            _activeTetra = null;
        }
    }
}