﻿using UnityEngine;
using UnityEditor;
using UnityEngine.Rendering;
using UnityEditor.Rendering.Universal;
 
public class LuxURPUniversalCustomShaderGUI : ShaderGUI
{

    public enum SurfaceType {
        Opaque,
        Transparent
    }

    public enum BlendMode {
        Alpha,   // Old school alpha-blending mode, fresnel does not affect amount of transparency
        Premultiply, // Physically plausible transparency mode, implemented as alpha pre-multiply
        Additive,
        Multiply
    }

    public override void OnGUI(MaterialEditor materialEditor, MaterialProperty[] properties)
    {
        Material material = materialEditor.target as Material;
        float surface = 0.0f;
        float surfaceOld = 0.0f;

        if (material.HasProperty("_LuxSurface")) {
            surface = surfaceOld = material.GetFloat("_LuxSurface");
            //surface = (SurfaceType)EditorGUILayout.EnumPopup("Surface Type", surface);
        } 

        base.OnGUI(materialEditor, properties);

    //  Double sided
        if (material.HasProperty("_Cull")) {
            var _Culling = ShaderGUI.FindProperty("_Cull", properties);
            if(_Culling.floatValue == 0.0f) {
                if (material.doubleSidedGI == false) {
                    Debug.Log ("Material " + material.name + ": Double Sided Global Illumination enabled.", (Object)material);
                }
                material.doubleSidedGI = true;
            }
            else {
                if (material.doubleSidedGI == true) {
                    Debug.Log ("Material " + material.name + ": Double Sided Global Illumination disabled.", (Object)material);
                }
                material.doubleSidedGI = false;
            }
        }

    //  Emission
        if ( material.HasProperty("_Emission")) {
            if ( material.GetFloat("_Emission") == 1.0f) {
                material.globalIlluminationFlags = MaterialGlobalIlluminationFlags.BakedEmissive;
            }
            else {
                material.globalIlluminationFlags = MaterialGlobalIlluminationFlags.BakedEmissive;
                material.globalIlluminationFlags |= MaterialGlobalIlluminationFlags.EmissiveIsBlack;
            }
        }

    //  Get RenderQueue Offset - if any
        int QueueOffset = 0;
        if ( material.HasProperty("_QueueOffset") ) {
            QueueOffset = material.GetInt("_QueueOffset");
        }

    //  Alpha Testing
        bool enableAlphaTesting = false;
    //  Check old custom property
        if ( material.HasProperty("_EnableAlphaTesting")) {
            if ( material.GetFloat("_EnableAlphaTesting") == 1.0f ) {
                if( material.HasProperty("_AlphaFromMaskMap") && material.HasProperty("_MaskMap") ) {
                    if (material.GetFloat("_AlphaFromMaskMap") == 1.0f && material.GetFloat("_EnableMaskMap") == 1.0f) {
                        enableAlphaTesting = true;
                    }
                }
                else {
                    enableAlphaTesting = true;
                }
            }

            if(enableAlphaTesting) {
                material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest + QueueOffset;
                material.SetOverrideTag("RenderType", "TransparentCutout");
            }
            else {
                material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Geometry + QueueOffset;
                material.SetOverrideTag("RenderType", "Opaque");
            }
        }
    
    //  We also check for the "standard" property
        if ( material.HasProperty("_AlphaClip")) {

            bool isTransparent = false;
            if (material.HasProperty("_LuxSurface")) {
                if (material.GetFloat("_LuxSurface") == 1.0f) {
                    isTransparent = true;    
                }
            }

            if ( material.GetFloat("_AlphaClip") == 1.0f ) {
                if( material.HasProperty("_AlphaFromMaskMap") && material.HasProperty("_MaskMap") ) {
                    if (material.GetFloat("_AlphaFromMaskMap") == 1.0f && material.GetFloat("_EnableMaskMap") == 1.0f) {
                        enableAlphaTesting = true;
                    }
                }
                else {
                    enableAlphaTesting = true;
                }
            }
            if(enableAlphaTesting) {
                if (isTransparent) {
                    material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent + QueueOffset;
                    material.SetOverrideTag("RenderType", "Transparent");   
                }
                else {
                    material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.AlphaTest + QueueOffset;
                    material.SetOverrideTag("RenderType", "TransparentCutout");   
                }
                
            }
            else {
                if (isTransparent) {
                    material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Transparent + QueueOffset;
                    material.SetOverrideTag("RenderType", "Transparent");   
                }
                else {
                    material.renderQueue = (int)UnityEngine.Rendering.RenderQueue.Geometry + QueueOffset;
                    material.SetOverrideTag("RenderType", "Opaque"); 
                }
            }
        }

    //  Surface
        if (material.HasProperty("_LuxSurface")) {
            surface = material.GetFloat("_LuxSurface");
            if(surface != surfaceOld) {
                if (surface == 0) {
                    material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
                    material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
                    material.SetInt("_ZWrite", 1);
                    if ( !material.HasProperty("_AlphaClip")) {
                        material.SetOverrideTag("RenderType", "Opaque");
                        material.renderQueue = (int)RenderQueue.Geometry + QueueOffset;
                    }
                    material.SetShaderPassEnabled("ShadowCaster", true);
                }
                else {
                    //else {
                    //    material.SetInt("_SrcBlend", (int) UnityEngine.Rendering.BlendMode.SrcAlpha);
                    //    material.SetInt("_DstBlend", (int) UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);   
                    //}
                    material.SetInt("_ZWrite", 0);
                    if ( !material.HasProperty("_AlphaClip")) {
                        material.SetOverrideTag("RenderType", "Transparent");
                        material.renderQueue = (int)RenderQueue.Transparent + QueueOffset;
                    }
                    material.SetShaderPassEnabled("ShadowCaster", false);
                }
            }
            if (surface == 1.0) {
                if(material.HasProperty("_LuxBlend")){
                    var blendMode = (BlendMode) material.GetFloat("_LuxBlend");
                    switch (blendMode)
                    {
                        case BlendMode.Alpha:
                            material.SetInt("_SrcBlend", (int) UnityEngine.Rendering.BlendMode.SrcAlpha);
                            material.SetInt("_DstBlend", (int) UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
                            material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                            break;
                        case BlendMode.Premultiply:
                            material.SetInt("_SrcBlend", (int) UnityEngine.Rendering.BlendMode.One);
                            material.SetInt("_DstBlend", (int) UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
                            material.EnableKeyword("_ALPHAPREMULTIPLY_ON");
                            break;
                        case BlendMode.Additive:
                            material.SetInt("_SrcBlend", (int) UnityEngine.Rendering.BlendMode.SrcAlpha);
                            material.SetInt("_DstBlend", (int) UnityEngine.Rendering.BlendMode.One);
                            material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                            break;
                        case BlendMode.Multiply:
                            material.SetInt("_SrcBlend", (int) UnityEngine.Rendering.BlendMode.DstColor);
                            material.SetInt("_DstBlend", (int) UnityEngine.Rendering.BlendMode.Zero);
                            material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
                            material.EnableKeyword("_ALPHAMODULATE_ON");
                            break;
                    }
                }
            }
        }
        else if(material.renderQueue == (int)RenderQueue.Geometry + QueueOffset) {
            material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.One);
            material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.Zero);
            material.SetInt("_ZWrite", 1);    
        }

    //  ColorMask - this is currently only used by the toon & outline shader
    //  So if detected base geometry only writes to depth. In order to prevent it from occluding the skybox
    //  we set the render queue to Transparent +
        if ( material.HasProperty("_ColorMask") ) {
            if (material.GetFloat("_ColorMask") == 0) {
                material.renderQueue = (int)RenderQueue.Transparent + QueueOffset;    
            }
        }

    //  Get rid of the normal map issue
        if ( material.HasProperty("_BumpMap") ) {
            if (material.HasProperty("_ApplyNormal") ) {
                if ( material.GetFloat("_ApplyNormal") == 0.0f && material.GetTexture("_BumpMap") == null ) {
                    //material.SetTexture("_BumpMap", Texture2D.normalTexture); // Is not linear?!
                    material.SetTexture("_BumpMap", Resources.Load("LuxURPdefaultBump") as Texture2D );
                }
            }
        }

    //  Needed to make the Selection Outline work
        if (material.HasProperty("_MainTex") && material.HasProperty("_BaseMap") ) {

        //  Alpha might be stored in the Mask Map
            bool copyMaskMap = false;
            if(material.HasProperty("_AlphaFromMaskMap") && material.HasProperty("_MaskMap")) {
                if (material.GetFloat("_AlphaFromMaskMap") == 1.0) {
                    copyMaskMap = true;
                }
            }
            if (copyMaskMap) {
                if (material.GetTexture("_MaskMap") != null) {
                    material.SetTexture("_MainTex", material.GetTexture("_MaskMap"));
                } 
            }
            else {
                if (material.GetTexture("_BaseMap") != null) {
                    material.SetTexture("_MainTex", material.GetTexture("_BaseMap"));
                }
            }
        }

    }
}