using UnityEngine;
using UnityEngine.Rendering;

[ExecuteInEditMode]
public class CommandBufferBlurRefraction : MonoBehaviour
{
    [SerializeField] private Camera cameraMain;
    [SerializeField] private Shader blurShader;
    private Material _material = null;
    private CommandBuffer _commandBuffer = null;

    private void Cleanup()
    {
        if (!_material)
        {
            cameraMain.RemoveCommandBuffer(CameraEvent.AfterSkybox, _commandBuffer);
            DestroyImmediate(_material);
            _material = null;
        }
    }

    public void OnDisable()
    {
        Cleanup();
    }

    private readonly int screenCopyID = Shader.PropertyToID("_ScreenCopyTexture");
    private readonly int blurredID = Shader.PropertyToID("_Temp1");
    private readonly int blurredID2 = Shader.PropertyToID("_Temp2");

    public void OnEnable()
    {
        if (!cameraMain)
            cameraMain = Camera.main;
        if (cameraMain == null)
            return;
        
        _material ??= new Material(blurShader) {hideFlags = HideFlags.HideAndDontSave};
        _commandBuffer ??= new CommandBuffer() {name = "Grab screen and blur"};

        // copy screen into temporary RT
        _commandBuffer.GetTemporaryRT(screenCopyID, -1, -1, 0, FilterMode.Bilinear);
        _commandBuffer.Blit(BuiltinRenderTextureType.CurrentActive, screenCopyID);

        // get two smaller RTs
        _commandBuffer.GetTemporaryRT(blurredID, -2, -2, 0, FilterMode.Bilinear);
        _commandBuffer.GetTemporaryRT(blurredID2, -2, -2, 0, FilterMode.Bilinear);

        // downsample screen copy into smaller RT, release screen RT
        _commandBuffer.Blit(screenCopyID, blurredID);
        _commandBuffer.ReleaseTemporaryRT(screenCopyID);

        // horizontal blur
        _commandBuffer.SetGlobalVector("offsets", new Vector4(2.0f / Screen.width, 0, 0, 0));
        _commandBuffer.Blit(blurredID, blurredID2, _material);
        // vertical blur
        _commandBuffer.SetGlobalVector("offsets", new Vector4(0, 2.0f / Screen.height, 0, 0));
        _commandBuffer.Blit(blurredID2, blurredID, _material);
        // horizontal blur
        _commandBuffer.SetGlobalVector("offsets", new Vector4(4.0f / Screen.width, 0, 0, 0));
        _commandBuffer.Blit(blurredID, blurredID2, _material);
        // vertical blur
        _commandBuffer.SetGlobalVector("offsets", new Vector4(0, 4.0f / Screen.height, 0, 0));
        _commandBuffer.Blit(blurredID2, blurredID, _material);

        _commandBuffer.SetGlobalTexture("_GrabBlurTexture", blurredID);

        cameraMain.AddCommandBuffer(CameraEvent.AfterSkybox, _commandBuffer);
    }
}