// Stylized Water 3 by Staggart Creations (http://staggart.xyz)
// COPYRIGHT PROTECTED UNDER THE UNITY ASSET STORE EULA (https://unity.com/legal/as-terms)
//    • Copying or referencing source code for the production of new asset store, or public, content is strictly prohibited!
//    • Uploading this file to a public repository will subject it to an automated DMCA takedown request.

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEditor.AnimatedValues;
using UnityEditor.Rendering;
using UnityEngine;
using UnityEngine.Rendering;
#if URP
using UnityEngine.Rendering.Universal;
#endif

namespace StylizedWater3
{
    public static class UI
    {
        private const string AssetIconData = "[encoded data, 39416 characters]";
        private static Texture _AssetIcon;
        public static Texture AssetIcon
        {
            get
            {
                if (_AssetIcon == null) _AssetIcon = CreateIcon(AssetIconData);
                return _AssetIcon;
            }
        }

        private const string DynamicEffectsAssetIconData = "[encoded data, 48988 characters]";
		private static Texture _DynamicEffectsAssetIcon;
        public static Texture DynamicEffectsAssetIcon
        {
            get
            {
                if (_DynamicEffectsAssetIcon == null) _DynamicEffectsAssetIcon = CreateIcon(DynamicEffectsAssetIconData);
                return _DynamicEffectsAssetIcon;
            }
        }

        private const string WarningIconData = "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";
        public static Texture WarningIcon;
        private const string ErrorIconData = "iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAD9klEQVR4Ae2bz2vUQBTHJ91S7FZ6EH/VY/GuRy8evHoVWnELgl68eBG8eNhfUPoXeOxB6B5WsGAPpZT+ISK46j/Q7MZiy2q75u04a35MkjeTl7fbrQMhmTcv8973k8nM0E2dQbslrIrj6G9rb+ntVNbVNbueBgPtfTNa6wUy/gdA/LCrfn8w1oo8IAZZoRwBVdHeapBlltSRjEEGgQoAj3gFhRACBQBe8cQQ8gIYj3hCCHkAjFc8EQRbADWWCU+JzDrnmBNsANTE+1Y9Kyf2dksIs4aJ2ou//6AlHq/hlq+PH16L/d0XhrmJ4aiUW+Um9l6TEWAvHrIplz2xs93xr9KPg72OWFjoYgXE/AxHAhZAPvHBLHe2g7Xw9cFeuG5bM4CAAUAnXgnSQaASr2IgIWQBoBevEgxCoBavYiAgpAEoTrxKECAUJV7FyICQBKB48SpBjrOEUNOF0gGYLvFKtdy7xCBEAUyn+BQIs/6uTjXDuR6sTOW1HAmjv1uY7gTtmZydRUeb7OvkRNfnZZ2xCBsfgB/eVQMBSwa+uVz5AHS7NwwyNfE16Dbuygeg55qIMvGNqzKw8AFw3SWxGZpwZZq6H1iePWF7BfQTkwFBtOvJMUxsZYT/vJC+CNf8LnwjAHJ1D+HJfslI+1ZGO2kzLwCvdx0BAHzYCi8AOQKyxLG9/5AIL4AuaiVgWwH4AfRQe4EpBuC6N7PGv9+O8UF0g3PhfQW8LmaCw/jg1CG8eAEcHmKWOIwPQhrOhReA17sWSqu6LquNN0Ez6whwBo8eBoPDhw3Flbm5Y387LHeDnheOs7go688rP0W/Px9uJK+NPnDi2wqDBinsr1KtqEUG8aHAvK8AhIaVoFSKPH7fDiPi9JR1BYB0+AF8/3pHLN/+DcFj5VvnbsxWsIF3DihYjEH3Y5oDDDLkcuWdBLlUGcS58ABmxUolyKs+kV9/BDPMe71SqQe7iK4CjSGQIj+Bede+Ekwgdr1e2xWfP92L2SkMUvzoRxHoUvcKAIQ6RTxtH09XXd+uPzaarpgp6ZdIbWcGRo14uFsHAOxFQ4AY4bLRDNcpa6trNeE4Df8Q0SMJAITng1C0eCES6aYBKBbC200hjo7k8fIV5fP+1xc8+RTx4JgFAHzoRwKIjxZqCAjxkAIGAPjRQdCJhwhQqCAgxUPI6DIItqQCEATBPmE5KcDQ/qt/KbU9q9FAPHTlWPzT1OR+RWIoHgBgXwHwVYXudVA9UpwtxEPYmei6iKw3hAxIkXr+PizFSwD24ZsTASGH+LwA4P7xQsgpngLA+CAQiKcCwA+BSDwlAD4IhOIhaZONEPhnlabvAMe5KTb7gHMjDpPohQfwB63ZMyXk5VWPAAAAAElFTkSuQmCC";
        public static Texture ErrorIcon;
        private const string InfoIconData = "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";
        public static Texture InfoIcon;

        public static readonly Color RedColor = new Color(1f, 0.31f, 0.34f);
        public static readonly Color OrangeColor= new Color(1f, 0.68f, 0f);
        public static readonly Color GreenColor = new Color(0.33f, 1f, 0f);

        private const float ANIM_SPEED = 12f;

        public static bool ExpandTooltips
        {
            get => SessionState.GetBool("SW3_UI_TOOLTIPS", false);
            set => SessionState.SetBool("SW3_UI_TOOLTIPS", value);
        }

        static UI()
        {
            WarningIcon = CreateIcon(WarningIconData);
            ErrorIcon = CreateIcon(ErrorIconData);
            InfoIcon = CreateIcon(InfoIconData);
        }

        public static Texture CreateIcon(string data)
        {
            byte[] bytes = System.Convert.FromBase64String(data);

            Texture2D icon = new Texture2D(32, 32, TextureFormat.RGBA32, false, false);
            icon.LoadImage(bytes, true);
            
            return icon;
        }

        public static void DrawHeader()
        {
            EditorGUILayout.LabelField($"{AssetInfo.ASSET_NAME}  - v{AssetInfo.INSTALLED_VERSION}", EditorStyles.centeredGreyMiniLabel);
            EditorGUILayout.Space();
        }
        
        public static string iconPrefix => EditorGUIUtility.isProSkin ? "d_" : "";

        public static void PropertyField(SerializedProperty prop, string label = null)
        {
            EditorGUILayout.PropertyField(prop, new GUIContent(label == null ? prop.displayName : label, prop.tooltip));
            
            if (ExpandTooltips && prop.tooltip != string.Empty) EditorGUILayout.HelpBox(prop.tooltip, MessageType.None);
        }
        
        public static void DrawRendererProperty(SerializedProperty property)
        {
            #if URP
            property.serializedObject.Update();
            int selectedRendererOption = property.intValue;
            EditorGUI.BeginChangeCheck();
            
            Rect controlRect = EditorGUILayout.GetControlRect(true);
            EditorGUI.BeginProperty(controlRect, new GUIContent(property.displayName, null, tooltip:property.tooltip), property);
            
            selectedRendererOption = EditorGUI.IntPopup(controlRect, new GUIContent(property.displayName, null, tooltip:property.tooltip), selectedRendererOption, PipelineUtilities.rendererDisplayList,PipelineUtilities.rendererIndexList);
            
            if (EditorGUI.EndChangeCheck())
            {
                //Clamp to valid index
                selectedRendererOption = PipelineUtilities.ValidateRenderer(selectedRendererOption);

                property.intValue = selectedRendererOption;
                property.serializedObject.ApplyModifiedProperties();
            }
            #else
            EditorGUILayout.PropertyField(property);
            #endif
        }

        private static float Sin(float offset = 0f)
        {
            return Mathf.Sin(offset + (float)EditorApplication.timeSinceStartup * Mathf.PI * 2f) * 0.5f + 0.5f;
        }
        
        public static void DrawNotification(string text, MessageType messageType = MessageType.None)
        {
            DrawHelpbox(text, messageType);
        }
        
        public static void DrawNotification(bool condition, string text, string buttonLabel, Action action, MessageType messageType = MessageType.None)
        {
            DrawHelpbox(text, messageType, condition, buttonLabel, action);
        }
        
        public static void DrawNotification(bool condition, string text, MessageType messageType = MessageType.None)
        {
            DrawHelpbox(text, messageType, condition, null, null);
        }

        public static void DrawRenderFeatureSetupError(ref bool isSetup)
        {
            using (new EditorGUI.DisabledGroupScope(Application.isPlaying))
            {
                bool state = isSetup;
                UI.DrawNotification(!isSetup, "The Stylized Water render feature is required to be set up, but is missing from the active renderer", "Fix", () =>
                {
                    StylizedWaterEditor.SetupRenderFeature();
                    state = true;
                }, MessageType.Error);

                isSetup = state;
            }
            if (isSetup == false && Application.isPlaying)
            {
                EditorGUILayout.HelpBox("Exit play-mode to perform this action", MessageType.Warning);
            }
        }
        
        private static void DrawHelpbox(string text, MessageType messageType = MessageType.None, bool condition = true, string buttonLabel = "", Action action = null)
        {
            if (!condition) return;
            
            Rect r = EditorGUILayout.GetControlRect();
            r.width -= 10f;

            Color sideColor = Color.gray;
            Texture icon = null;
            switch (messageType)
            {
                case (MessageType.None):
                    {
                        sideColor = Color.gray;
                    }
                    break;
                case (MessageType.Warning): //Warning
                    {
                        sideColor = Color.Lerp(OrangeColor, OrangeColor * 1.20f, Sin(r.y));
                        icon = WarningIcon;
                    }
                    break;
                case (MessageType.Error): //Error
                    {
                        sideColor = Color.Lerp(RedColor, RedColor * 1.33f, Sin(r.y));
                        icon = ErrorIcon;
                    }
                    break;
                case (MessageType.Info): //Info
                    {
                        sideColor = Color.Lerp(new Color(1f, 1f, 1f), new Color(0.9f, 0.9f, 0.9f), Sin(r.y));
                        icon = InfoIcon;
                    }
                    break;
            }
            
            float width = r.width;
            //float rightPadding = 
            float height = EditorStyles.helpBox.CalcHeight(new GUIContent(text), EditorGUIUtility.currentViewWidth) + (EditorStyles.label.lineHeight * 2f);
            r.height = height;

            Rect btnRect = r;
            GUIContent btnContent = null;
            //Showing a button instead
            if (action != null)
            {
                icon = null;

                btnContent = new GUIContent(" " + buttonLabel, EditorGUIUtility.IconContent("SceneLoadIn").image, "Execute suggested action");
                float size = EditorStyles.toolbarButton.CalcSize(btnContent).x + 5f;
                btnRect.width = size;
                btnRect.x = width - size;
                btnRect.height = EditorStyles.miniButtonMid.fixedHeight+5f;
                //Vertical center
                btnRect.y += (height * 0.5f) - (btnRect.height * 0.5f);
            }

            Rect iconRect = r;
            if (icon != null) 
            {
                float size = Mathf.Min(height * 0.75f, 50f);
                iconRect = r;
                iconRect.x = r.width - size;
                iconRect.width = size;
                iconRect.height = iconRect.width;
                //Vertical center
                iconRect.y += (height * 0.5f) - (iconRect.height * 0.5f);
                
                //Recalculate text height
                height = EditorStyles.helpBox.CalcHeight(new GUIContent(text),
                    EditorGUIUtility.currentViewWidth - size) + (EditorStyles.label.lineHeight * 2f);
                r.height = height;
            }

            float backgroundTint = EditorGUIUtility.isProSkin ? 0.4f : 1f;
            EditorGUI.DrawRect(r, new Color(backgroundTint, backgroundTint, backgroundTint, 0.2f));

            Rect colorRect = r;
            colorRect.width = 7f;

            EditorGUI.DrawRect(colorRect, sideColor);

            Rect textRect = r;
            textRect.x += colorRect.width + 10f;

            //Shrink text area on right side to make room
            if (icon != null) textRect.width -= iconRect.width * 2f;
            if(action != null) textRect.width -= btnRect.width + 50f;

            GUI.Label(textRect, new GUIContent(text), Styles.NotificationArea);

            if (icon != null)
            {
                GUI.DrawTexture(iconRect, icon, ScaleMode.ScaleToFit);
            }

            if (action != null)
            {
                if (GUI.Button(btnRect, btnContent))
                {
                    action?.Invoke();
                }
            }

            GUILayout.Space(height - EditorStyles.label.lineHeight); //17=default line height
        }

        public static void DrawStatusBox(string prefix, string statusText, MessageType messageType = MessageType.None)
        {
            using (new EditorGUILayout.HorizontalScope())
            {
                EditorGUILayout.LabelField(prefix, GUILayout.MaxWidth(EditorGUIUtility.labelWidth));

                Color defaultColor = GUI.contentColor;
                
                using (new EditorGUILayout.HorizontalScope(EditorStyles.textField))
                {
                    switch (messageType)
                    {
                        case MessageType.Error: GUI.contentColor = RedColor;
                            break;
                        case MessageType.Warning : GUI.contentColor = OrangeColor;
                            break;
                        case MessageType.Info: GUI.contentColor = GreenColor;
                            break;
                    }

                    EditorGUILayout.LabelField(statusText);
                    GUI.contentColor = defaultColor;
                }
            }
        }
        
        public static void DrawExtension(string name, string description, bool installed, int assetID, Texture icon)
        {
            EditorGUILayout.BeginHorizontal();
            {
                Color defaultColor = GUI.contentColor;

                GUILayout.Label(icon, GUILayout.MaxHeight(100f));

                EditorGUILayout.BeginVertical();
                {
                    EditorGUILayout.LabelField(name, Styles.BoldLabel, GUILayout.Height(20));

                    GUILayout.Space(5);
                    EditorGUILayout.LabelField(description, Styles.WordWrapLabel);

                    if (installed == false)
                    {
                        using (new EditorGUILayout.HorizontalScope(EditorStyles.textField))
                        {
                            EditorGUILayout.LabelField("Not Installed", GUILayout.MaxWidth((75f)));

                            GUILayout.FlexibleSpace();

                            if (GUILayout.Button(UI.Styles.AssetStoreBtnContent))
                            {
                                Application.OpenURL($"https://assetstore.unity.com/packages/slug/{assetID}?aid=1011l7Uk8&pubref=sw3editor_extensions");
                            }
                        }
                    }
                }
                EditorGUILayout.EndVertical();
            }
            EditorGUILayout.EndHorizontal();
        }

        public static void DrawIntegration(FogIntegration.Integration integration)
        {
            EditorGUILayout.LabelField(integration.name, EditorStyles.boldLabel);
            EditorGUILayout.BeginHorizontal();
            {
                Color defaultColor = GUI.contentColor;

                GUILayout.Label(integration.thumbnail, GUILayout.Height(50f), GUILayout.Width(50f));

                EditorGUILayout.BeginVertical();
                {
                    GUILayout.Space(5);

                    if (integration.asset != FogIntegration.Assets.None && integration.asset != FogIntegration.Assets.UnityFog)
                    {
                        using (new EditorGUILayout.HorizontalScope(EditorStyles.textField))
                        {
                            if (integration.installed) GUI.contentColor = GreenColor;
                            if (!integration.installed) GUI.contentColor = UI.OrangeColor;
                            EditorGUILayout.LabelField(integration.installed ? "Installed" : "Not Installed", GUILayout.MaxWidth((75f)));
                            GUI.contentColor = defaultColor;

                            GUILayout.FlexibleSpace();
                            
                            if (GUILayout.Button(UI.Styles.AssetStoreBtnContent))
                            {
                                AssetInfo.OpenAssetStore(integration.url);
                            }
                        }

                        GUILayout.Space(5);
                    }

                    if (!integration.installed)
                    {
                        //UI.DrawNotification("Shader library for asset not found in project", MessageType.Error);
                    }
                }
                EditorGUILayout.EndVertical();
            }
            EditorGUILayout.EndHorizontal();
        }

        public static bool DrawSetupItem(Installer.SetupItem item)
        {
            Texture icon = Styles.CheckMark;

            switch (item.state)
            {
                case MessageType.Error: icon = Styles.ErrorIcon; break;
                case MessageType.Warning: icon = Styles.WarningIcon; break;
                case MessageType.None: icon = Styles.CheckMark; break;
                case MessageType.Info: icon = Styles.InfoIcon; break;
            }
            
            
            using (new EditorGUILayout.HorizontalScope(EditorStyles.label))
            {
                Color defaultColor = GUI.contentColor;

                switch (item.state)
                {
                    case MessageType.Error: GUI.contentColor = UI.RedColor;
                        break;                    
                    case MessageType.Warning: GUI.contentColor = UI.OrangeColor;
                        break;
                    case MessageType.None: GUI.contentColor = UI.GreenColor;
                        break;
                }
                
                EditorGUILayout.LabelField(new GUIContent("  " + item.name, icon), EditorStyles.boldLabel);
                
                GUI.contentColor = defaultColor;
                
                if (item.action != null)
                {
                    if (GUILayout.Button(item.actionName))
                    {
                        item.ExecuteAction();
                        return true;
                    }
                }
            }

            GUILayout.Space(-3f);
            
            using (new EditorGUILayout.HorizontalScope())
            {
                GUILayout.Space(25f);
                EditorGUILayout.LabelField(item.description, Styles.WordWrapLabel);
            }
            
            GUILayout.Space(-7f);
            EditorGUILayout.LabelField("", GUI.skin.horizontalSlider, GUILayout.Height(12f));
            
            GUILayout.Space(-3f);
            
            //No action clicked
            return false;
        }
        
        public static void DrawH2(string text)
        {
            Rect backgroundRect = EditorGUILayout.GetControlRect();
            backgroundRect.height = 25f;
            
            var labelRect = backgroundRect;

            // Background rect should be full-width
            backgroundRect.xMin = 0f;

            // Background
            float backgroundTint = (EditorGUIUtility.isProSkin ? 0.1f : 1f);
            EditorGUI.DrawRect(backgroundRect, new Color(backgroundTint, backgroundTint, backgroundTint, 0.2f));

            // Title
            EditorGUI.LabelField(labelRect, new GUIContent(text), Styles.H2);
            
            EditorGUILayout.Space(backgroundRect.height * 0.5f);
        }
        
        public static void DrawFooter()
        {
            GUILayout.Space(5f);

            Rect rect = EditorGUILayout.GetControlRect();
            
            if (rect.Contains(Event.current.mousePosition))
            {
                EditorGUIUtility.AddCursorRect(new Rect(Event.current.mousePosition.x, Event.current.mousePosition.y, 27, 27), MouseCursor.Link);
                EditorGUI.DrawRect(rect, Color.gray * (EditorGUIUtility.isProSkin ? 0.66f : 0.20f));
            }
            
            if (GUI.Button(rect,new GUIContent("- Staggart Creations -", "Open website"), EditorStyles.centeredGreyMiniLabel))
            {
                Application.OpenURL("http://staggart.xyz");
            }
        }
        
        public static class Material
        {
            //Section toggles
            public class Section
            {
                public bool Expanded
                {
                    get { return SessionState.GetBool(id, false); }
                    set { SessionState.SetBool(id, value); }
                }
                public AnimBool anim;

                public readonly string id;
                public GUIContent title;

                public Section(MaterialEditor owner, string id, GUIContent title)
                {
                    this.id = AssetInfo.ASSET_ABRV + "_" + id + "_SECTION";
                    this.title = title;

                    anim = new AnimBool(true);
                    anim.valueChanged.AddListener(owner.Repaint);
                    anim.speed = ANIM_SPEED;
                    anim.target = Expanded;
                }
                
                public void DrawHeader(Action clickAction)
                {
                    UI.Material.DrawHeader(title, Expanded, clickAction);
                    anim.target = Expanded;
                }
            }
            
            private const float HeaderHeight = 25f;

            //https://github.com/Unity-Technologies/Graphics/blob/d0473769091ff202422ad13b7b764c7b6a7ef0be/com.unity.render-pipelines.core/Editor/CoreEditorUtils.cs#L460
            public static bool DrawHeader(GUIContent content, bool isExpanded, Action clickAction = null)
            {
#if URP
                CoreEditorUtils.DrawSplitter();
#endif

                Rect backgroundRect = GUILayoutUtility.GetRect(1f, HeaderHeight);
                
                //Negate room made for parameter locking (material variants functionality)
                backgroundRect.xMin -= 15f;

                var labelRect = backgroundRect;
                labelRect.xMin += 10f;
                labelRect.xMax -= 20f + 16 + 5;

                var foldoutRect = backgroundRect;
                foldoutRect.xMin -= 8f;
                foldoutRect.y += 0f;
                foldoutRect.width = HeaderHeight;
                foldoutRect.height = HeaderHeight;

                // Background rect should be full-width
                backgroundRect.xMin = 0f;
                backgroundRect.width += 4f;

                // Background
                float backgroundTint = (EditorGUIUtility.isProSkin ? 0.1f : 1f);
                if (backgroundRect.Contains(Event.current.mousePosition)) backgroundTint *= EditorGUIUtility.isProSkin ? 1.5f : 0.9f;
                
                EditorGUI.DrawRect(backgroundRect, new Color(backgroundTint, backgroundTint, backgroundTint, 0.2f));

                // Title
                EditorGUI.LabelField(labelRect, content, EditorStyles.boldLabel);

                // Foldout
                GUI.Label(foldoutRect, new GUIContent(isExpanded ? "−" : "≡"), EditorStyles.boldLabel);
                
                // Handle events
                var e = Event.current;

                if (e.type == EventType.MouseDown)
                {
                    if (backgroundRect.Contains(e.mousePosition))
                    {
                        if (e.button == 0)
                        {
                            isExpanded = !isExpanded;
                            if(clickAction != null) clickAction.Invoke();
                        }

                        e.Use();
                    }
                }
                
                return isExpanded;
            }
            
            public static void DrawIntSlider(MaterialProperty prop, string label = null, string tooltip = null)
            {
                MaterialEditor.BeginProperty(prop);

                EditorGUI.BeginChangeCheck();
                EditorGUI.showMixedValue = prop.hasMixedValue;
                
                float value = (float)EditorGUILayout.IntSlider(new GUIContent(label ?? prop.displayName, null, tooltip), (int)prop.floatValue, (int)prop.rangeLimits.x, (int)prop.rangeLimits.y);
                
                if (ExpandTooltips && tooltip != string.Empty) EditorGUILayout.HelpBox(tooltip, MessageType.None);

                if (EditorGUI.EndChangeCheck())
                    prop.floatValue = value;
                EditorGUI.showMixedValue = false;
                
                MaterialEditor.EndProperty();
            }

            public static void DrawFloatField(MaterialProperty prop, string label = null, string tooltip = null)
            {
                MaterialEditor.BeginProperty(prop);

                EditorGUI.BeginChangeCheck();
                EditorGUI.showMixedValue = prop.hasMixedValue;
                
                float value = EditorGUILayout.FloatField(new GUIContent(label ?? prop.displayName, null, tooltip), prop.floatValue, GUILayout.MaxWidth(EditorGUIUtility.labelWidth + 50f));
                
                if (ExpandTooltips && tooltip != null) EditorGUILayout.HelpBox(tooltip, MessageType.None);

                if (EditorGUI.EndChangeCheck())
                    prop.floatValue = value;
                EditorGUI.showMixedValue = false;
                
                MaterialEditor.EndProperty();
            }

            public static void DrawFloatTicker(MaterialProperty prop, string label = null, string tooltip = null, bool showReverse = false)
            {
                MaterialEditor.BeginProperty(prop);

                EditorGUI.BeginChangeCheck();
                EditorGUI.showMixedValue = prop.hasMixedValue;
                
                float value = m_DrawFloatTicker(prop.floatValue, label ?? prop.displayName, tooltip, showReverse);
                
                if (EditorGUI.EndChangeCheck())
                    prop.floatValue = value;
                EditorGUI.showMixedValue = false;
                
                MaterialEditor.EndProperty();
            }

            private static float m_DrawFloatTicker(float value, string label = null, string tooltip = null, bool showReverse = false)
            {
                EditorGUILayout.BeginHorizontal();
                EditorGUILayout.PrefixLabel(new GUIContent(label, null, tooltip));
                if (GUILayout.Button(new GUIContent("«", "-0.1"), EditorStyles.miniButtonLeft, GUILayout.Width(20)))
                {
                    value -= 0.1f;
                }
                if (GUILayout.Button(new GUIContent("‹", "-0.01"), EditorStyles.miniButtonMid, GUILayout.Width(20)))
                {
                    value -= 0.01f;
                }
                
                value = EditorGUILayout.FloatField(value, GUILayout.MaxWidth(EditorGUIUtility.fieldWidth));

                if (GUILayout.Button(new GUIContent("›", "+0.01"), EditorStyles.miniButtonMid, GUILayout.Width(20)))
                {
                    value += 0.01f;
                }
                if (GUILayout.Button(new GUIContent("»", "+0.1"), EditorStyles.miniButtonRight, GUILayout.Width(20)))
                {
                    value += 0.1f;
                }

                if (showReverse)
                {
                    if (GUILayout.Button("Reverse", EditorStyles.miniButton, GUILayout.MaxWidth(70f)))
                    {
                        value = -value;
                    }
                }
                EditorGUILayout.EndHorizontal();
                
                if (ExpandTooltips && tooltip != null) EditorGUILayout.HelpBox(tooltip, MessageType.None);

                return value;
            }
            
            public static void DrawMinMaxSlider(MaterialProperty prop, float min, float max, string label = null, string tooltip = null)
            {
                MaterialEditor.BeginProperty(prop);

                float minVal = prop.vectorValue.x;
                float maxVal = prop.vectorValue.y;

                EditorGUI.BeginChangeCheck();
                EditorGUI.showMixedValue = prop.hasMixedValue;
                
                using (new EditorGUILayout.HorizontalScope())
                {
                    EditorGUILayout.LabelField(new GUIContent(label, null, tooltip), GUILayout.MaxWidth(EditorGUIUtility.labelWidth));
                    minVal = EditorGUILayout.FloatField(minVal, GUILayout.Width(EditorGUIUtility.fieldWidth));
                    EditorGUILayout.MinMaxSlider(ref minVal, ref maxVal, min, max);
                    maxVal = EditorGUILayout.FloatField(maxVal, GUILayout.Width(EditorGUIUtility.fieldWidth));
                }
                
                if (ExpandTooltips && tooltip != null) EditorGUILayout.HelpBox(tooltip, MessageType.None);

                if (EditorGUI.EndChangeCheck())
                {
                    prop.vectorValue = new Vector4(minVal, maxVal);
                }
                EditorGUI.showMixedValue = false;
                
                MaterialEditor.EndProperty();
            }

            public static void DrawColorField(MaterialProperty prop, bool hdr, string name = null, string tooltip = null)
            {
                MaterialEditor.BeginProperty(prop);

                EditorGUI.BeginChangeCheck();
                EditorGUI.showMixedValue = prop.hasMixedValue;

                Color color;
                using (new EditorGUILayout.HorizontalScope())
                {
                    EditorGUILayout.PrefixLabel(new GUIContent(name ?? prop.displayName, tooltip));
                    color = EditorGUILayout.ColorField(new GUIContent("", null, tooltip), prop.colorValue, true, true, hdr, GUILayout.MaxWidth(60f));
                    
                    EditorGUILayout.LabelField($"Opacity: {Math.Round(prop.colorValue.a * 100f, 2)}%", EditorStyles.miniLabel);
                }

                if (ExpandTooltips && tooltip != null) EditorGUILayout.HelpBox(tooltip, MessageType.None);

                if (EditorGUI.EndChangeCheck())
                    prop.colorValue = color;
                EditorGUI.showMixedValue = false;
                
                MaterialEditor.EndProperty();
            }

            public static void DrawVector2(MaterialProperty prop, string label, string tooltip = null)
            {
                MaterialEditor.BeginProperty(prop);

                EditorGUI.BeginChangeCheck();
                EditorGUI.showMixedValue = prop.hasMixedValue;

                Vector2 value;
                using (new EditorGUILayout.HorizontalScope())
                {
                    EditorGUILayout.PrefixLabel(new GUIContent(label, tooltip));
                    value = EditorGUILayout.Vector2Field(new GUIContent("", null, tooltip), prop.vectorValue);
                }
                
                if (ExpandTooltips && tooltip != null) EditorGUILayout.HelpBox(tooltip, MessageType.None);

                if (EditorGUI.EndChangeCheck())
                    prop.vectorValue = value;
                EditorGUI.showMixedValue = false;

                MaterialEditor.EndProperty();
            }
            
            public static void DrawVector2Ticker(MaterialProperty prop, string label, string tooltip = null)
            {
                MaterialEditor.BeginProperty(prop);

                EditorGUI.BeginChangeCheck();
                EditorGUI.showMixedValue = prop.hasMixedValue;

                Vector2 value = prop.vectorValue;
                using (new EditorGUILayout.HorizontalScope())
                {
                    EditorGUILayout.PrefixLabel(new GUIContent(label, tooltip));

                    if (GUILayout.Button(new GUIContent("«", "-0.1"), EditorStyles.miniButtonLeft, GUILayout.Width(20)))
                    {
                        value.x -= 0.1f;
                        value.y -= 0.1f;
                    }
                    if (GUILayout.Button(new GUIContent("‹", "-0.01"), EditorStyles.miniButtonMid, GUILayout.Width(20)))
                    {
                        value.x -= 0.01f;
                        value.y -= 0.01f;
                    }
                    
                    value = EditorGUILayout.Vector2Field(new GUIContent("", null, tooltip), value, GUILayout.MaxWidth(EditorGUIUtility.fieldWidth * 2f));

                    if (GUILayout.Button(new GUIContent("›", "+0.01"), EditorStyles.miniButtonMid, GUILayout.Width(20)))
                    {
                        value.x += 0.01f;
                        value.y += 0.01f;
                    }
                    if (GUILayout.Button(new GUIContent("»", "+0.1"), EditorStyles.miniButtonRight, GUILayout.Width(20)))
                    {
                        value.x += 0.1f;
                        value.y += 0.1f;
                    }
                }
                
                if (ExpandTooltips && tooltip != null) EditorGUILayout.HelpBox(tooltip, MessageType.None);

                if (EditorGUI.EndChangeCheck())
                {
                    value.x = Mathf.Max(value.x, 0.01f);
                    value.y = Mathf.Max(value.y, 0.01f);
                    
                    prop.vectorValue = value;
                }
                EditorGUI.showMixedValue = false;
                
                MaterialEditor.EndProperty();
            }
        }

        public class Styles
        {
            public static GUIStyle _NotificationArea;
            public static GUIStyle NotificationArea
            {
                get
                {
                    if (_NotificationArea == null)
                    {
                        _NotificationArea = new GUIStyle(EditorStyles.label)
                        {
                            //margin = new RectOffset(15, 0, 15, 0),
                            //padding = new RectOffset(5, 5, 5, 5),
                            richText = true,
                            wordWrap = true,
                            clipping = TextClipping.Overflow,
                        };
                    }

                    return _NotificationArea;
                }
            }
            
            private static Texture _CheckMark;
            public static Texture CheckMark
            {
                get
                {
                    if (_CheckMark == null)
                    {
                        _CheckMark = EditorGUIUtility.IconContent("TestPassed").image;

                    }
                    return _CheckMark;
                }
            }
            
            private static Texture _InfoIcon;
            public static Texture InfoIcon
            {
                get
                {
                    if (_InfoIcon == null)
                    {
                        _InfoIcon = EditorGUIUtility.IconContent("console.infoicon.sml").image;
                    }
                    return _InfoIcon;
                }
            }
            
            private static Texture _ErrorIcon;
            public static Texture ErrorIcon
            {
                get
                {
                    if (_ErrorIcon == null)
                    {
                        _ErrorIcon = EditorGUIUtility.IconContent("console.erroricon.sml").image;
                    }
                    return _ErrorIcon;
                }
            }
            
            private static Texture _WarningIcon;
            public static Texture WarningIcon
            {
                get
                {
                    if (_WarningIcon == null)
                    {
                        _WarningIcon = EditorGUIUtility.IconContent("console.warnicon.sml").image;
                    }
                    return _WarningIcon;
                }
            }


            private static GUIStyle _UpdateText;
            public static GUIStyle UpdateText
            {
                get
                {
                    if (_UpdateText == null)
                    {
                        _UpdateText = new GUIStyle("Button")
                        {
                            //fontSize = 10,
                            alignment = TextAnchor.MiddleLeft,
                            stretchWidth = false,
                        };
                    }

                    return _UpdateText;
                }
            }

            private static GUIStyle _Footer;
            public static GUIStyle Footer
            {
                get
                {
                    if (_Footer == null)
                    {
                        _Footer = new GUIStyle(EditorStyles.centeredGreyMiniLabel)
                        {
                            richText = true,
                            alignment = TextAnchor.MiddleCenter,
                            wordWrap = true,
                            fontSize = 12
                        };
                    }

                    return _Footer;
                }
            }

            private static GUIStyle _Button;
            public static GUIStyle Button
            {
                get
                {
                    if (_Button == null)
                    {
                        _Button = new GUIStyle(GUI.skin.button)
                        {
                            alignment = TextAnchor.MiddleLeft,
                            stretchWidth = true,
                            richText = true,
                            wordWrap = true,
                            padding = new RectOffset()
                            {
                                left = 7,
                                right = 0,
                                top = 5,
                                bottom = 5
                            },
                            imagePosition = ImagePosition.ImageLeft
                        };
                    }

                    return _Button;
                }
            }

            private static GUIContent _AssetStoreBtnContent;
            public static GUIContent AssetStoreBtnContent
            {
                get
                {
                    if (_AssetStoreBtnContent == null)
                    {
                        _AssetStoreBtnContent = new GUIContent("  View on Asset Store ", EditorGUIUtility.IconContent("Asset Store").image, "Open web page.\n\nURL may contain an affiliate ID, this commission helps to fund the purchase of new assets in order to investigate/develop integrations for them.");
                    }

                    return _AssetStoreBtnContent;
                }
            }

            private static GUIStyle _H1;
            public static GUIStyle H1
            {
                get
                {
                    if (_H1 == null)
                    {
                        _H1 = new GUIStyle(GUI.skin.label)
                        {
                            richText = true,
                            alignment = TextAnchor.MiddleCenter,
                            wordWrap = true,
                            fontSize = 18,
                            fontStyle = FontStyle.Normal
                        };
                    }

                    return _H1;
                }
            }
            
            private static GUIStyle _H2;
            public static GUIStyle H2
            {
                get
                {
                    if (_H2 == null)
                    {
                        _H2 = new GUIStyle(GUI.skin.label)
                        {
                            richText = true,
                            alignment = TextAnchor.MiddleLeft,
                            wordWrap = true,
                            fontSize = 14,
                            fontStyle = FontStyle.Bold
                        };
                    }

                    return _H2;
                }
            }
            
            private static GUIStyle _Section;
            public static GUIStyle Section
            {
                get
                {
                    if (_Section == null)
                    {
                        _Section = new GUIStyle(EditorStyles.helpBox)
                        {
                            margin = new RectOffset(0, 0, -5, 5),
                            padding = new RectOffset(10, 10, 5, 5),
                            clipping = TextClipping.Clip,
                        };
                    }

                    return _Section;
                }
            }
            
            private static GUIStyle _WordWrapLabel;
            public static GUIStyle WordWrapLabel
            {
                get
                {
                    if (_WordWrapLabel == null) 
                    {
                        _WordWrapLabel = new GUIStyle(EditorStyles.label);
                        _WordWrapLabel.wordWrap = true;
                        _WordWrapLabel.richText = true;
                    }
                    
                    return _WordWrapLabel;
                }
            }
            
            private static GUIStyle _BoldLabel;
            public static GUIStyle BoldLabel
            {
                get
                {
                    if (_BoldLabel == null) 
                    {
                        _BoldLabel = new GUIStyle(EditorStyles.largeLabel);
                        _BoldLabel.fontStyle = FontStyle.Bold;
                    }
                    
                    return _BoldLabel;
                }
            }

            private static GUIStyle _Tab;
            public static GUIStyle Tab
            {
                get
                {
                    if (_Tab == null)
                    {
                        _Tab = new GUIStyle(EditorStyles.miniButtonMid)
                        {
                            alignment = TextAnchor.MiddleCenter,
                            stretchWidth = true,
                            richText = true,
                            wordWrap = true,
                            fontSize = 16,
                            fixedHeight = 27.5f,
                            fontStyle = FontStyle.Bold,
                            padding = new RectOffset()
                            {
                                left = 14,
                                right = 14,
                                top = 3,
                                bottom = 3
                            }
                        };
                    }

                    return _Tab;
                }
            }
            
            private static GUIStyle s_CenterBoldLabel;
            public static GUIStyle CenterBoldLabel
            {
                get
                {
                    if (s_CenterBoldLabel == null) {
                        s_CenterBoldLabel = new GUIStyle(EditorStyles.largeLabel);
                        s_CenterBoldLabel.alignment = TextAnchor.UpperCenter;
                        s_CenterBoldLabel.padding = new RectOffset();
                        s_CenterBoldLabel.fontStyle = FontStyle.Bold;
                    }
                    return s_CenterBoldLabel;
                }
            }
            
            private static GUIStyle s_AddOnTitle;
            private static GUIStyle AddOnTitle
            {
                get
                {
                    if (s_AddOnTitle == null) {
                        s_AddOnTitle = new GUIStyle(CenterBoldLabel);
                        s_AddOnTitle.fontSize = 14;
                        s_AddOnTitle.alignment = TextAnchor.MiddleLeft;
                    }
                    return s_AddOnTitle;
                }
            }
            
        }
    }
}