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

[ExecuteInEditMode]
public class HoleControl : MonoBehaviour
{
    public static HoleControl Instance { get; private set; }

    public static int _HoleProj_VP = Shader.PropertyToID("_HoleProj_VP");
    public static int _HoleTex = Shader.PropertyToID("_HoleTex");
    public static int _HoleRSpeed = Shader.PropertyToID("_HoleRSpeed");

    public static int _holeCutoffValue = Shader.PropertyToID("_UseHole");

    public Texture2D m_holeTex = null;
    public float m_speed = 5f;

    public float m_fov = 200;
    public float m_width = 1920;
    public float m_height = 1080;

    [Header("目标")]
    public Transform m_target;
    public LayerMask m_hitLayer;
    public Vector3 m_boxHalfExtents = new Vector3(5, 5, 20);
#if UNITY_EDITOR
    [Header("查看碰撞区域")]
    public Transform m_CastBox;
#endif

    public const int g_maxCount = 10;

    public Renderer[][] m_renderer = null;

    MaterialPropertyBlock m_block = null;

    Collider[] m_hits = new Collider[g_maxCount];


    Vector3 m_center;
    private Camera m_mainCamera;
    private Camera mainCamera
    {
        get
        {
            if(m_mainCamera == null)
            {
                m_mainCamera = Camera.main;
            }
            return m_mainCamera;
        }
    }

    private void resetRenderer()
    {
        if (m_renderer == null)
            return;

        for (int i = 0; i < g_maxCount; ++i)
        {
            var rs = m_renderer[i];
            if (rs == null)
                continue;

            foreach (var render in rs)
            {
                render?.SetPropertyBlock(null);
            }

            m_renderer[i] = null;
        }

    }

    private void OnDisable()
    {
        resetRenderer();
        Instance = null;
    }

    private void OnEnable()
    {
        Instance = this;
    }

    // Update is called once per frame
    void Update()
    {
        if (m_renderer == null)
        {
            m_renderer = new Renderer[g_maxCount][];
        }
        resetRenderer();
        if (m_target == null)
            return;
        var camera = mainCamera;

        var p = Matrix4x4.Perspective(m_fov, m_width / m_height, 0.01f, 1000);
        Shader.SetGlobalMatrix(_HoleProj_VP, p * camera.worldToCameraMatrix);
        Shader.SetGlobalTexture(_HoleTex, m_holeTex);
        Shader.SetGlobalFloat(_HoleRSpeed, m_speed);

        if (m_block == null)
        {
            m_block = new MaterialPropertyBlock();
            m_block.SetFloat(_holeCutoffValue, 0.5f);
        }

        var dir = camera.transform.position - m_target.position;
        m_center = m_target.position + dir * 0.5f;
        m_boxHalfExtents.z = Vector3.Distance(camera.transform.position, m_target.position) * 0.5f;
#if UNITY_EDITOR
        if (m_CastBox)
        {
            m_CastBox.position = m_center;
            m_CastBox.localScale = m_boxHalfExtents * 2;
            m_CastBox.rotation = Quaternion.LookRotation(dir);
        }
#endif
        var count = Physics.OverlapBoxNonAlloc(m_center, m_boxHalfExtents, m_hits, Quaternion.LookRotation(dir), m_hitLayer);
        for (int i = 0; i < count; ++i)
        {
            var renders = m_hits[i].gameObject.GetComponentsInChildren<Renderer>();
            m_renderer[i] = renders;
            foreach (var r in renders)
            {
                r.SetPropertyBlock(m_block);
            }
        }
    }
}
