﻿using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition;
using System;

[Serializable, VolumeComponentMenu("Post-processing/Snapshot Pro (HDRP)/Halftone")]
public sealed class Halftone : CustomPostProcessVolumeComponent, IPostProcessComponent
{
    [Tooltip("Enable the effect?")]
    public BoolParameter enabled = new BoolParameter(false);

    [Tooltip("The texture used to determine the shape of the halftone 'dots'.")]
    public TextureParameter halftoneTexture = new TextureParameter(null);

    [Tooltip("How soft the transition between light and dark is.")]
    public ClampedFloatParameter softness = new ClampedFloatParameter(0.5f, 0.0f, 1.0f);

    [Tooltip("Size of the halftone 'dots' on the screen.")]
    public ClampedFloatParameter textureSize = new ClampedFloatParameter(4.0f, 1.0f, 10.0f);

    [Tooltip("Use this vector to remap the minimum and maximum luminance values used in calculations. Default is (0, 1).")]
    public Vector2Parameter minMaxLuminance = new Vector2Parameter(new Vector2(0.0f, 1.0f));

    [Tooltip("Color of the darkened sections.")]
    public ColorParameter darkColor = new ColorParameter(Color.black);

    [Tooltip("Color of the lighter sections.")]
    public ColorParameter lightColor = new ColorParameter(Color.white);

    [Tooltip("Use the Scene Color instead of Light Color.")]
    public BoolParameter useSceneColor = new BoolParameter(false);

    Material m_Material;

    public bool IsActive() => m_Material != null && enabled.value;

    // Remember to add this post process in the Custom Post Process Orders list 
    // (Project Settings > HDRP Default Settings).
    public override CustomPostProcessInjectionPoint injectionPoint =>
        CustomPostProcessInjectionPoint.AfterPostProcess;

    const string kShaderName = "SnapshotProHDRP/Halftone";

    public override void Setup()
    {
        if (Shader.Find(kShaderName) != null)
        {
            m_Material = new Material(Shader.Find(kShaderName));
        }
        else
        {
            Debug.LogError($"Unable to find shader '{kShaderName}' for the Halftone effect.");
        }
    }

    public override void Render(CommandBuffer cmd, HDCamera camera, RTHandle source, RTHandle destination)
    {
        if (m_Material == null)
        {
            return;
        }

        if (useSceneColor.value)
        {
            cmd.EnableShaderKeyword("USE_SCENE_TEXTURE_ON");
        }
        else
        {
            cmd.DisableShaderKeyword("USE_SCENE_TEXTURE_ON");
        }

        if (halftoneTexture.value != null)
        {
            m_Material.SetTexture("_HalftoneTexture", halftoneTexture.value);
        }
        else
        {
            m_Material.SetTexture("_HalftoneTexture", Texture2D.whiteTexture);
        }

        m_Material.SetFloat("_Softness", softness.value);
        m_Material.SetFloat("_TextureSize", textureSize.value);
        m_Material.SetVector("_MinMaxLuminance", minMaxLuminance.value);
        m_Material.SetColor("_DarkColor", darkColor.value);
        m_Material.SetColor("_LightColor", lightColor.value);

        m_Material.SetTexture("_InputTexture", source);
        HDUtils.DrawFullScreen(cmd, m_Material, destination);
    }

    public override void Cleanup()
    {
        CoreUtils.Destroy(m_Material);
    }
}
