using System.Collections.Generic;
using AsteroidGame.Entities.Structures.Scripts;
using UnityEngine;
using UnityEngine.InputSystem;

namespace AsteroidGame.Handlers
{
    public class BuildingHandler : HandlerBase
    {
        [Header("Config")] 
        [SerializeField] private Color colorGhost = new Color(1f, 1f, 1f, 0.12f);
        [SerializeField] private Color colorBuildingBlocked = new Color(1f, 0f, 0f, 0.12f);
        [SerializeField] private Material ghostStructureMaterial;

        [Header("State")] 
        [SerializeField] private bool isBuilding;
        [SerializeField] private int buildingSelector;

        [Header("Structures")] 
        [SerializeField] private StructureBaseScriptableObject availableStructuresObject;

        #region Private

        private Dictionary<int, StructureBase> _availableStructures = new();
        [SerializeField] private Color colorCurrent;
        private Camera _camera;
        [SerializeField] private List<StructureBase> activeStructures;
        private Vector3 _tempVec;
        private Plane _buildPlane;
        private StructureBase _tempStructure;
        private StructureBase _ghostStructure;
        private MeshRenderer[] _ghostStructureMeshRenderers;

        #endregion
        
        protected override void OnEnable()
        {
            base.OnEnable();
            for (int i = 0; i < availableStructuresObject.structureList.Count; i++)
            {
                _availableStructures.Add(i, availableStructuresObject.structureList[i]);
            }
            _camera = Camera.main;
            _buildPlane = new Plane(Vector3.up, Vector3.zero);
            activeStructures.Clear();
        }

        private void Update()
        {
            if (!isBuilding) return;
            _ghostStructure.transform.position = GetPlanePoint();
            SetGhostColor(_ghostStructure.BuildPlacementBlocked ? colorBuildingBlocked : colorGhost);
        }

        private void SetGhostColor(Color newColor)
        {
            if (newColor == colorCurrent) return;
            foreach (var meshRenderer in _ghostStructureMeshRenderers)
            {
                meshRenderer.material.color = newColor;
            }

            colorCurrent = newColor;
        }

        protected override void OnLeftClick(InputAction.CallbackContext context)
        {
            PlaceStructure();
        }

        protected override void OnRightClick(InputAction.CallbackContext context)
        {
            AbortPlaceStructure();
        }

        protected override void OnBuild(InputAction.CallbackContext context)
        {
            EnterBuildMode(buildingSelector);
        }

        public void PlaceStructure()
        {
            if (!isBuilding) return;
            if (_ghostStructure.BuildPlacementBlocked) return;
            if (!Keyboard.current.shiftKey.isPressed)
            {
                DestroyGhostStructure();
                isBuilding = false;
            }

            SpawnStructure();
            
        }

        public void AbortPlaceStructure()
        {
            if (!isBuilding) return;
            DestroyGhostStructure();
            isBuilding = false;
        }

        public void EnterBuildMode(int index)
        {
            if (isBuilding) return;
            isBuilding = true;
            SetBuildingIndex(index);
            SpawnGhostStructure();
        }

        private void SpawnGhostStructure()
        {
            _ghostStructure = Instantiate(_availableStructures[buildingSelector], GetPlanePoint(), Quaternion.identity, transform);
            _ghostStructure.name = "GhostStructure";

            var rb = _ghostStructure.gameObject.AddComponent<Rigidbody>();
            rb.useGravity = false;

            _ghostStructureMeshRenderers = _ghostStructure.GetComponentsInChildren<MeshRenderer>();

            foreach (var meshRenderer in _ghostStructureMeshRenderers)
            {
                meshRenderer.material = ghostStructureMaterial;
            }

            _ghostStructure.GetComponent<StructureBase>().enabled = false;
        }

        private void DestroyGhostStructure()
        {
            Destroy(_ghostStructure.gameObject);
        }

        private void SpawnStructure()
        {
            _tempStructure = Instantiate(_availableStructures[buildingSelector], GetPlanePoint(), Quaternion.identity, transform);
            activeStructures.Add(_tempStructure);
        }

        #region Getters
        
        private Vector3 GetPlanePoint()
        {
            Ray ray = _camera.ScreenPointToRay(Mouse.current.position.ReadValue());
            if (_buildPlane.Raycast(ray, out float distance))
            {
                return ray.GetPoint(distance);
            }
            
            print("BuildPlaneNotHit");
            return Vector3.zero;
        }
        
        public Dictionary<int, StructureBase> GetAvailableStructures()
        {
            return _availableStructures;
        }
        
        public List<StructureBase> GetActiveStructures()
        {
            return activeStructures;
        }

        #endregion

        #region Setters

        public void SetBuildingIndex(int index)
        {
            buildingSelector = index;
        }

        #endregion
        
    }
}