using System;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif

// Source: https://answers.unity.com/questions/489942/how-to-make-a-readonly-property-in-inspector.html

/// <summary>
/// Display a field with disabled read-only controls in the inspector.
/// Works with CustomPropertyDrawers.
/// </summary>
/// <seealso cref="ReadOnlyAttribute"/>
/// <seealso cref="BeginShowOnlyGroupAttribute"/>
/// <seealso cref="EndShowOnlyGroupAttribute"/>
public class ShowOnlyAttribute : PropertyAttribute { }

/// <summary>
/// Display a field as a custom read-only text in the inspector.
/// CustomPropertyDrawers will not work when this attribute is used.
/// </summary>
/// <seealso cref="ShowOnlyAttribute"/>
/// <seealso cref="BeginShowOnlyGroupAttribute"/>
/// <seealso cref="EndShowOnlyGroupAttribute"/>
public class ReadOnlyAttribute : PropertyAttribute { }

/// <summary>
/// Display one or more fields as read-only in the inspector.
/// Use <see cref="EndShowOnlyGroupAttribute"/> to close the group.
/// Works with CustomPropertyDrawers.
/// </summary>
/// <seealso cref="EndShowOnlyGroupAttribute"/>
/// <seealso cref="ShowOnlyAttribute"/>
public class BeginShowOnlyGroupAttribute : PropertyAttribute { }

/// <summary>
/// Use with <see cref="BeginShowOnlyGroupAttribute"/>.
/// Close the read-only group and resume editable fields.
/// </summary>
/// <seealso cref="BeginShowOnlyGroupAttribute"/>
/// <seealso cref="ShowOnlyAttribute"/>
public class EndShowOnlyGroupAttribute : PropertyAttribute { }

// Custom Drawers declarations must be in a if Unity Editor assembly condition to allow a project to compile
#if UNITY_EDITOR
    [CustomPropertyDrawer(typeof(ShowOnlyAttribute))]
    public class ShowOnlyDrawer : PropertyDrawer
    {
        public override float GetPropertyHeight( SerializedProperty property, GUIContent label ) {
            return EditorGUI.GetPropertyHeight( property, label, true );
        }
        
        public override void OnGUI( Rect position, SerializedProperty prop, GUIContent label )
        {
            var currentGuiState = GUI.enabled;
            GUI.enabled = false;
            EditorGUI.PropertyField(position, prop, label, true);
            GUI.enabled = currentGuiState;
        }
    }

    [CustomPropertyDrawer( typeof( ReadOnlyAttribute ) )]
    public class ReadOnlyDrawer : PropertyDrawer {
 
        public override float GetPropertyHeight( SerializedProperty property, GUIContent label ) {
            return EditorGUI.GetPropertyHeight( property, label, true );
        }
 
        public override void OnGUI( Rect position, SerializedProperty prop, GUIContent label )
        {
            EditorGUI.LabelField(position, label.text,PropToString(prop));
        }

        private string PropToString(SerializedProperty prop)
        {
            string valueStr;

            switch (prop.propertyType)
            {
                case SerializedPropertyType.Generic:
                    valueStr = "Array";
                    break;
                case SerializedPropertyType.Integer:
                    valueStr = prop.intValue.ToString();
                    break;
                case SerializedPropertyType.Boolean:
                    valueStr = prop.boolValue.ToString();
                    break;
                case SerializedPropertyType.Float:
                    valueStr = prop.floatValue.ToString("0.00000");
                    break;
                case SerializedPropertyType.String:
                    valueStr = prop.stringValue;
                    break;
                case SerializedPropertyType.Enum:
                    valueStr = prop.enumDisplayNames[prop.enumValueIndex];
                    break;
                case SerializedPropertyType.ObjectReference:
                    try {
                        valueStr = prop.objectReferenceValue.ToString();
                    } catch (NullReferenceException) {
                        valueStr = "Object ToString not defined";
                    }
                    break;
                case SerializedPropertyType.Vector4:
                    valueStr = prop.vector4Value.ToString();
                    break;
                case SerializedPropertyType.Vector3:
                    valueStr = prop.vector3Value.ToString();
                    break;
                case SerializedPropertyType.Vector2:
                    valueStr = prop.vector2Value.ToString();
                    break;
                case SerializedPropertyType.Vector2Int:
                    valueStr = prop.vector2IntValue.ToString();
                    break;
                case SerializedPropertyType.Vector3Int:
                    valueStr = prop.vector3IntValue.ToString();
                    break;
                default:
                    valueStr = "( " + prop.type + " isn't supported )";
                    break;
            }

            return valueStr;
        }
    }
 
    [CustomPropertyDrawer( typeof( BeginShowOnlyGroupAttribute ) )]
    public class BeginShowOnlyGroupDrawer : DecoratorDrawer {
 
        public override float GetHeight() { return 0; }
 
        public override void OnGUI( Rect position )
        {
            GUI.enabled = false;
        }
 
    }
 
    [CustomPropertyDrawer( typeof( EndShowOnlyGroupAttribute ) )]
    public class EndShowOnlyGroupDrawer : DecoratorDrawer {
 
        public override float GetHeight() { return 0; }
 
        public override void OnGUI( Rect position )
        {
            GUI.enabled = true;
        }
    }
#endif