// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

using System;

namespace Microsoft.AspNetCore.Razor.Language.Components
{
    internal static class TagHelperBoundAttributeDescriptorExtensions
    {
        public static bool IsDelegateProperty(this BoundAttributeDescriptor attribute)
        {
            var key = ComponentMetadata.Component.DelegateSignatureKey;
            return
                attribute.Metadata.TryGetValue(key, out var value) &&
                string.Equals(value, bool.TrueString);
        }

        /// <summary>
        /// Gets a value indicating whether the attribute is of type <c>EventCallback</c> or
        /// <c>EventCallback{T}</c>
        /// </summary>
        /// <param name="attribute">The <see cref="BoundAttributeDescriptor"/>.</param>
        /// <returns><c>true</c> if the attribute is an event callback, otherwise <c>false</c>.</returns>
        public static bool IsEventCallbackProperty(this BoundAttributeDescriptor attribute)
        {
            var key = ComponentMetadata.Component.EventCallbackKey;
            return
                attribute.Metadata.TryGetValue(key, out var value) &&
                string.Equals(value, bool.TrueString);
        }

        public static bool IsGenericTypedProperty(this BoundAttributeDescriptor attribute)
        {
            return
                attribute.Metadata.TryGetValue(ComponentMetadata.Component.GenericTypedKey, out var value) &&
                string.Equals(value, bool.TrueString);
        }

        public static bool IsTypeParameterProperty(this BoundAttributeDescriptor attribute)
        {
             return
                attribute.Metadata.TryGetValue(ComponentMetadata.Component.TypeParameterKey, out var value) &&
                string.Equals(value, bool.TrueString);
        }

        public static bool IsCascadingTypeParameterProperty(this BoundAttributeDescriptor attribute)
        {
              return
                attribute.Metadata.TryGetValue(ComponentMetadata.Component.TypeParameterIsCascadingKey, out var value) &&
                string.Equals(value, bool.TrueString);
        }

        public static bool IsWeaklyTyped(this BoundAttributeDescriptor attribute)
        {
            var key = ComponentMetadata.Component.WeaklyTypedKey;
            return
                attribute.Metadata.TryGetValue(key, out var value) &&
                string.Equals(value, bool.TrueString);
        }

        /// <summary>
        /// Gets a value that indicates whether the property is a child content property. Properties are
        /// considered child content if they have the type <c>RenderFragment</c> or <c>RenderFragment{T}</c>.
        /// </summary>
        /// <param name="attribute">The <see cref="BoundAttributeDescriptor"/>.</param>
        /// <returns>Returns <c>true</c> if the property is child content, otherwise <c>false</c>.</returns>
        public static bool IsChildContentProperty(this BoundAttributeDescriptor attribute)
        {
            var key = ComponentMetadata.Component.ChildContentKey;
            return
                attribute.Metadata.TryGetValue(key, out var value) &&
                string.Equals(value, bool.TrueString);
        }

        /// <summary>
        /// Gets a value that indicates whether the property is a child content property. Properties are
        /// considered child content if they have the type <c>RenderFragment</c> or <c>RenderFragment{T}</c>.
        /// </summary>
        /// <param name="attribute">The <see cref="BoundAttributeDescriptorBuilder"/>.</param>
        /// <returns>Returns <c>true</c> if the property is child content, otherwise <c>false</c>.</returns>
        public static bool IsChildContentProperty(this BoundAttributeDescriptorBuilder attribute)
        {
            var key = ComponentMetadata.Component.ChildContentKey;
            return
                attribute.Metadata.TryGetValue(key, out var value) &&
                string.Equals(value, bool.TrueString);
        }

        /// <summary>
        /// Gets a value that indicates whether the property is a parameterized child content property. Properties are
        /// considered parameterized child content if they have the type <c>RenderFragment{T}</c> (for some T).
        /// </summary>
        /// <param name="attribute">The <see cref="BoundAttributeDescriptor"/>.</param>
        /// <returns>Returns <c>true</c> if the property is parameterized child content, otherwise <c>false</c>.</returns>
        public static bool IsParameterizedChildContentProperty(this BoundAttributeDescriptor attribute)
        {
            return attribute.IsChildContentProperty() &&
                !string.Equals(attribute.TypeName, ComponentsApi.RenderFragment.FullTypeName, StringComparison.Ordinal);
        }

        /// <summary>
        /// Gets a value that indicates whether the property is a parameterized child content property. Properties are
        /// considered parameterized child content if they have the type <c>RenderFragment{T}</c> (for some T).
        /// </summary>
        /// <param name="attribute">The <see cref="BoundAttributeDescriptor"/>.</param>
        /// <returns>Returns <c>true</c> if the property is parameterized child content, otherwise <c>false</c>.</returns>
        public static bool IsParameterizedChildContentProperty(this BoundAttributeDescriptorBuilder attribute)
        {
            return attribute.IsChildContentProperty() &&
                !string.Equals(attribute.TypeName, ComponentsApi.RenderFragment.FullTypeName, StringComparison.Ordinal);
        }

        /// <summary>
        /// Gets a value that indicates whether the property is used to specify the name of the parameter
        /// for a parameterized child content property.
        /// </summary>
        /// <param name="attribute">The <see cref="BoundAttributeDescriptor"/>.</param>
        /// <returns>
        /// Returns <c>true</c> if the property specifies the name of a parameter for a parameterized child content,
        /// otherwise <c>false</c>.
        /// </returns>
        public static bool IsChildContentParameterNameProperty(this BoundAttributeDescriptor attribute)
        {
            var key = ComponentMetadata.Component.ChildContentParameterNameKey;
            return
                attribute.Metadata.TryGetValue(key, out var value) &&
                string.Equals(value, bool.TrueString);
        }
    }
}
