using System;

namespace InABox.Core
{
    public enum Editable
    {
        Enabled,
        Disabled,
        Hidden,
        /// <summary>
        /// Disabled when using a DynamicGrid with DirectEdit option set, but enabled in editor
        /// </summary>
        DisabledOnDirectEdit
    }

    /// <summary>
    /// Set whether or not this property is editable, overriding any <see cref="BaseEditor"/> on this property or any sub-properties.
    /// </summary>
    /// <remarks>
    /// What this actually does is that when <see cref="DatabaseSchema"/> is loading a property, it checks to find the outer-most parent property
    /// of that property with an <see cref="EditableAttribute"/>, or if the property has one of its own. If so, it overrides the <see cref="Editable"/>
    /// property of that property's <see cref="IProperty.Editor"/>, combining using the <see cref="EditableUtils.Combine(Editable, Editable)"/> function.
    /// </remarks>
    public class EditableAttribute: Attribute
    {
        public Editable Editable { get; set; }

        public EditableAttribute(Editable editable)
        {
            Editable = editable;
        }
    }

    public static class EditableUtils
    {
        public static bool IsEditable(this Editable editable)
        {
            return editable == Editable.Enabled || editable == Editable.DisabledOnDirectEdit;
        }
        public static bool IsDirectEditable(this Editable editable)
        {
            return editable == Editable.Enabled;
        }

        public static bool ColumnVisible(this Editable editable)
        {
            return editable != Editable.Hidden;
        }

        public static bool EditorVisible(this Editable editable)
        {
            return editable != Editable.Hidden;
        }

        /// <summary>
        /// Combine (restrictively) two editable enums.
        /// </summary>
        /// <param name="editable"></param>
        /// <param name="other"></param>
        /// <returns></returns>
        public static Editable Combine(this Editable editable, Editable other)
        {
            switch (editable)
            {
                case Editable.Enabled:
                    return other;
                case Editable.DisabledOnDirectEdit:
                    if (other == Editable.Disabled || other == Editable.Hidden)
                        return other;
                    return editable;
                case Editable.Disabled:
                    if (other == Editable.Hidden)
                        return other;
                    return editable;
                case Editable.Hidden:
                default:
                    return editable;
            }
        }
    }
}