using UnityEngine;

public class ComputeController : MonoBehaviour
{
    [Header("Connections")]
    [SerializeField] private ComputeShader _computeShader;
    [SerializeField] private Texture2D _inputTexture;
    [SerializeField] private RenderTexture _resultTexture;
    [SerializeField] private Material _resultMaterial;

    [Header("State")]
    [SerializeField] private int _width;
    [SerializeField] private int _height;
    [SerializeField] private float _sin;

    private int _kernelHandle;
    private const int NumThreadX = 8;
    private const int NumThreadY = 8;

    #region ShaderVariables

    private static readonly int Result = Shader.PropertyToID("result");
    private static readonly int SourceTexture = Shader.PropertyToID("source_texture");
    private static readonly int SinScaled = Shader.PropertyToID("sin_scaled");
    private static readonly int MainTex = Shader.PropertyToID("_MainTex");

    #endregion

    #region Start

    private void Start()
    {
        InitializeTextures();

        InitializeShader();

        RunComputeShader();
    }

    private void InitializeTextures()
    {
        _width = _inputTexture.width;
        _height = _inputTexture.height;
        _resultTexture = new(_width, _height, 24);
        _resultTexture.name = "ResultTexture";
        _resultTexture.enableRandomWrite = true;
        _resultTexture.Create();

        _resultMaterial.SetTexture(MainTex, _resultTexture);
    }

    private void InitializeShader()
    {
        _kernelHandle = _computeShader.FindKernel("cs_main");
        _computeShader.SetTexture(_kernelHandle, SourceTexture, _inputTexture);
        _computeShader.SetTexture(_kernelHandle, Result, _resultTexture);
        RunComputeShader();
    }

    #endregion

    #region Update

    // private void Update()
    // {
    //     ShaderUpdate();
    //
    //     _resultMaterial.mainTexture = _resultTexture;
    // }

    private void ShaderUpdate()
    {
        _sin = (Mathf.Sin(Time.unscaledTime) + 1) / 2;
        _computeShader.SetFloat(SinScaled, _sin);
        RunComputeShader();
    }

    private void RunComputeShader()
    {
        _computeShader.Dispatch(_kernelHandle, _width / NumThreadX, _height / NumThreadY, 1);
    }

    #endregion
}