using System;
using System.Collections.Generic;
using Intrepid.Utilities;
using Sirenix.OdinInspector;
using UnityEngine;

namespace Intrepid.Gameplay.Flooring
{
    public struct VisibilityRequest
    {
        public float VisibilityOriginY { get; set; }
        public float UpperThreshold { get; set; }
        public float UpperMax { get; set; }
        public float LowerThreshold { get; set; }
        public float LowerMin { get; set; }
        public Color LowerTintColor { get; set; }
    }

    public sealed class FloorVisualGroup : MonoBehaviour
    {
        private static readonly int VisibilityOriginYId = Shader.PropertyToID("_VisibilityOriginY");
        private static readonly int UpperThresholdId = Shader.PropertyToID("_UpperThreshold");
        private static readonly int UpperMaxId = Shader.PropertyToID("_UpperMax");
        private static readonly int LowerThresholdId = Shader.PropertyToID("_LowerThreshold");
        private static readonly int LowerMinId = Shader.PropertyToID("_LowerMin");
        private static readonly int LowerTintColorId = Shader.PropertyToID("_LowerTintColor");

        [GroupInjections, SerializeField] private List<Renderer> meshRenderers = new();

        private MaterialPropertyBlock Block { get; set; }

        private void Awake()
        {
            Block = new MaterialPropertyBlock();
        }

        [GroupDebug, Button(ButtonSizes.Medium)]
        private void Detect()
        {
            meshRenderers.Clear();

            var rendererArray = GetComponentsInChildren<Renderer>(true);

            if (rendererArray.Length > 0)
            {
                meshRenderers.AddRange(rendererArray);
            }
        }

        public void SetVisibility(VisibilityRequest request)
        {
            foreach (var meshRenderer in meshRenderers)
            {
                if (meshRenderer.IsNull()) continue;

                meshRenderer.GetPropertyBlock(Block);

                Block.SetFloat(VisibilityOriginYId, request.VisibilityOriginY);
                Block.SetFloat(UpperThresholdId, request.UpperThreshold);
                Block.SetFloat(UpperMaxId, request.UpperMax);
                Block.SetFloat(LowerThresholdId, request.LowerThreshold);
                Block.SetFloat(LowerMinId, request.LowerMin);
                Block.SetColor(LowerTintColorId, request.LowerTintColor);

                meshRenderer.SetPropertyBlock(Block);
            }
        }
    }
}