__all__ = (
    'create_attachment_input', 'create_attachment_media', 'create_button', 'create_channel_select', 'create_container',
    'create_label', 'create_media_gallery', 'create_mentionable_select', 'create_role_select', 'create_row',
    'create_section', 'create_separator', 'create_string_select', 'create_text_display', 'create_text_input',
    'create_thumbnail_media', 'create_user_select'
)

from .component import Component, ComponentType


def create_button(
    label = ...,
    emoji = ...,
    *,
    custom_id = ...,
    enabled = ...,
    sku_id = ...,
    style = ...,
    url = ...,
):
    """
    Creates a new button component.
    
    Parameters
    -----------
    label : `None | str`, Optional
        Label of the component.
    
    emoji : ``None | Emoji``, Optional
        Emoji of the button if applicable.
    
    custom_id : `None | str`, Optional (Keyword only)
        Custom identifier to detect which button was clicked by the user.
        
        > Mutually exclusive with the `url` and `sku_id` fields.
    
    enabled : `bool`, Optional (Keyword only)
        Whether the button is enabled.
    
    sku_id : ``int | SKU``, Optional (Keyword only)
        Purchasable stock keeping unit identifier.
        
        > Mutually exclusive with the `custom_id` and `url` fields.
    
    style : `None`, ``int | ButtonStyle``, Optional (Keyword only)
        The button's style.
    
    url : `None | str`, Optional (Keyword only)
        Url to redirect to when clicking on the button.
        
        > Mutually exclusive with the `custom_id` and `sku_id` fields.
    
    Returns
    -------
    button : ``Component``
    
    Raises
    ------
    TypeError
        - If a parameter's type is incorrect.
    ValueError
        - If a parameter's value is incorrect.
        - `url` and `custom_id` are mutually exclusive.
    """
    return Component(
        ComponentType.button,
        button_style = style,
        custom_id = custom_id,
        label = label,
        enabled = enabled,
        emoji = emoji,
        sku_id = sku_id,
        url = url,
    )


def create_row(
    *components,
):
    """
    Creates a row component from the given components.
    
    Parameters
    ----------
    *components : ``Component``
        Sub components.
    
    Returns
    -------
    row : ``Component``
    
    Raises
    ------
    TypeError
        - If a parameter's type is incorrect.
    """
    return Component(
        ComponentType.row,
        components = components,
    )


def create_string_select(
    options,
    custom_id = ...,
    *,
    enabled = ...,
    placeholder = ...,
    max_values = ...,
    min_values = ...,
    required = ...,
):
    """
    Creates a new string select.
    
    Parameters
    ----------
    options : `None` or `iterable` of ``StringSelectOption``
        Options of the select.
    
    custom_id : `None | str`, Optional
        Custom identifier to detect which component was used by the user.
    
    enabled : `bool`, Optional (Keyword only)
        Whether the button is enabled.
    
    placeholder : `None | str`, Optional (Keyword only)
        Placeholder text of the select.
    
    max_values : `int`, Optional (Keyword only)
        The maximal amount of options to select.
        
    min_values : `int`, Optional (Keyword only)
        The minimal amount of options to select.
    
    required : `None | bool`, Optional (Keyword only)
        Whether the field is required to be fulfilled.
    
    Returns
    -------
    string_select : ``Component``
    
    Raises
    ------
    TypeError
        - If a parameter's type is incorrect.
    ValueError
        - If a parameter's value is incorrect.
    """
    return Component(
        ComponentType.string_select,
        custom_id = custom_id,
        enabled = enabled,
        options = options,
        max_values = max_values,
        min_values = min_values,
        placeholder = placeholder,required = required,
    )


def create_text_input(
    label = ...,
    *,
    custom_id = ...,
    max_length = ...,
    min_length = ...,
    placeholder = ...,
    required = ...,
    style = ...,
    value = ...,
):
    """
    Creates a new text input. Can be used inside of forms.
    
    Parameters
    ----------
    label : `None | str`, Optional
        Label of the component.
    
    custom_id : `None | str`, Optional (Keyword only)
        Custom identifier to detect which text input was clicked by the user.
        
        If not given, is autogenerated form the `label` parameter.
    
    max_length : `int`, Optional (Keyword only)
        The maximal length of the inputted text.
    
    min_length : `int`, Optional (Keyword only)
        The minimal length of the inputted text.
    
    placeholder : `None | str`, Optional (Keyword only)
        Placeholder text of the input.
    
    required : `None | bool`, Optional (Keyword only)
        Whether the field is required to be fulfilled.
        
        If not given, or given as `None`, will default to `True` if `min_length` is defined as higher than `0`.
    
    style : ``None | int | TextInputStyle``, Optional (Keyword only)
        The text input's style.
    
    value : `None | str`, Optional (Keyword only)
        The text input's default value.
    
    Returns
    -------
    text_input : ``Component``
    
    Raises
    ------
    TypeError
        - If a parameter's type is incorrect.
    ValueError
        - If a parameter's value is incorrect.
    """
    return Component(
        ComponentType.text_input,
        custom_id = custom_id,
        label = label,
        max_length = max_length,
        min_length = min_length,
        placeholder = placeholder,
        required = required,
        text_input_style = style,
        value = value,
    )


def create_user_select(
    custom_id = ...,
    *,
    default_values = ...,
    enabled = ...,
    placeholder = ...,
    max_values = ...,
    min_values = ...,
    required = ...,
):
    """
    Creates a new user select.
    
    Parameters
    ----------
    custom_id : `None | str`, Optional
        Custom identifier to detect which component was used by the user.
    
    default_values : `None | iterable<ClientUserBase | EntitySelectDefaultValue | tuple>`, Optional (Keyword only)
        Entities presented in the select by default.
    
    enabled : `bool`, Optional (Keyword only)
        Whether the button is enabled.
    
    placeholder : `None | str`, Optional (Keyword only)
        Placeholder text of the select.
    
    max_values : `int`, Optional (Keyword only)
        The maximal amount of options to select.
        
    min_values : `int`, Optional (Keyword only)
        The minimal amount of options to select.
    
    required : `None | bool`, Optional (Keyword only)
        Whether the field is required to be fulfilled.
    
    Returns
    -------
    user_select : ``Component``
    
    Raises
    ------
    TypeError
        - If a parameter's type is incorrect.
    ValueError
        - If a parameter's value is incorrect.
    """
    return Component(
        ComponentType.user_select,
        custom_id = custom_id,
        default_values = default_values,
        enabled = enabled,
        max_values = max_values,
        min_values = min_values,
        placeholder = placeholder,
        required = required,
    )


def create_role_select(
    custom_id = ...,
    *,
    default_values = ...,
    enabled = ...,
    placeholder = ...,
    max_values = ...,
    min_values = ...,
    required = ...,
):
    """
    Creates a new role select.
    
    Parameters
    ----------
    custom_id : `None | str`, Optional
        Custom identifier to detect which component was used by the user.
    
    default_values : `None | iterable<Role | EntitySelectDefaultValue | tuple>`, Optional (Keyword only)
        Entities presented in the select by default.
    
    enabled : `bool`, Optional (Keyword only)
        Whether the button is enabled.
    
    placeholder : `None | str`, Optional (Keyword only)
        Placeholder text of the select.
    
    max_values : `int`, Optional (Keyword only)
        The maximal amount of options to select.
        
    min_values : `int`, Optional (Keyword only)
        The minimal amount of options to select.
    
    required : `None | bool`, Optional (Keyword only)
        Whether the field is required to be fulfilled.
    
    Returns
    -------
    role_select : ``Component``
    
    Raises
    ------
    TypeError
        - If a parameter's type is incorrect.
    ValueError
        - If a parameter's value is incorrect.
    """
    return Component(
        ComponentType.role_select,
        custom_id = custom_id,
        default_values = default_values,
        enabled = enabled,
        max_values = max_values,
        min_values = min_values,
        placeholder = placeholder,
        required = required,
    )


def create_mentionable_select(
    custom_id = ...,
    *,
    default_values = ...,
    enabled = ...,
    placeholder = ...,
    max_values = ...,
    min_values = ...,
    required = ...,
):
    """
    Creates a new mentionable (user & role) select.
    
    Parameters
    ----------
    custom_id : `None | str`, Optional
        Custom identifier to detect which component was used by the user.
    
    default_values : `None | iterable<ClientUserBase | Role | EntitySelectDefaultValue | tuple>` \
            , Optional (Keyword only)
        Entities presented in the select by default.
    
    enabled : `bool`, Optional (Keyword only)
        Whether the button is enabled.
    
    placeholder : `None | str`, Optional (Keyword only)
        Placeholder text of the select.
    
    max_values : `int`, Optional (Keyword only)
        The maximal amount of options to select.
        
    min_values : `int`, Optional (Keyword only)
        The minimal amount of options to select.
    
    required : `None | bool`, Optional (Keyword only)
        Whether the field is required to be fulfilled.
    
    Returns
    -------
    mentionable_select : ``Component``
    
    Raises
    ------
    TypeError
        - If a parameter's type is incorrect.
    ValueError
        - If a parameter's value is incorrect.
    """
    return Component(
        ComponentType.mentionable_select,
        custom_id = custom_id,
        default_values = default_values,
        enabled = enabled,
        max_values = max_values,
        min_values = min_values,
        placeholder = placeholder,
        required = required,
    )


def create_channel_select(
    custom_id = ...,
    *,
    channel_types = ...,
    default_values = ...,
    enabled = ...,
    placeholder = ...,
    max_values = ...,
    min_values = ...,
    required = ...,
):
    """
    Creates a new channel select.
    
    Parameters
    ----------
    custom_id : `None | str`, Optional
        Custom identifier to detect which component was used by the user.
    
    channel_types : `None`, `tuple` of (``ChannelType``, `int`), Optional (Keyword only)
        The allowed channel types by the select.
    
    default_values : `None | iterable<ClientUserBase | Channel | EntitySelectDefaultValue | tuple>` \
            , Optional (Keyword only)
        Entities presented in the select by default.
    
    enabled : `bool`, Optional (Keyword only)
        Whether the button is enabled.
    
    placeholder : `None | str`, Optional (Keyword only)
        Placeholder text of the select.
    
    max_values : `int`, Optional (Keyword only)
        The maximal amount of options to select.
        
    min_values : `int`, Optional (Keyword only)
        The minimal amount of options to select.
    
    required : `None | bool`, Optional (Keyword only)
        Whether the field is required to be fulfilled.
    
    Returns
    -------
    channel_select : ``Component``
    
    Raises
    ------
    TypeError
        - If a parameter's type is incorrect.
    ValueError
        - If a parameter's value is incorrect.
    """
    return Component(
        ComponentType.channel_select,
        channel_types = channel_types,
        custom_id = custom_id,
        default_values = default_values,
        enabled = enabled,
        max_values = max_values,
        min_values = min_values,
        placeholder = placeholder,
        required = required,
    )


def create_section(
    *components,
    thumbnail = ...,
):
    """
    Creates a section component from the given components.
    
    Parameters
    ----------
    *components : ``Component``
        Sub components.
    
    thumbnail : ``None | Component``, Optional (Keyword only)
        The thumbnail or other accessory (button) of a section component.
    
    Returns
    -------
    row : ``Component``
    
    Raises
    ------
    TypeError
        - If a parameter's type is incorrect.
    """
    return Component(
        ComponentType.section,
        components = components,
        thumbnail = thumbnail,
    )


def create_text_display(
    content = ...,
):
    """
    Creates a new text display component. Can be used inside of forms.
    
    Parameters
    ----------
    content : `None | str`, Optional
        The content shown on the component.
    
    Returns
    -------
    text : ``Component``
    
    Raises
    ------
    TypeError
        - If a parameter's type is incorrect.
    ValueError
        - If a parameter's value is incorrect.
    """
    return Component(
        ComponentType.text_display,
        content = content,
    )


def create_thumbnail_media(
    media,
    *,
    description = ...,
    spoiler = ...,
):
    """
    Creates a new thumbnail media component. Can be used inside of forms.
    
    Parameters
    ----------
    media : ``str | MediaInfo``
        The media of the component.
    
    description : `None | str`, Optional (Keyword only)
        Description of the component's media.
    
    spoiler : `bool` Optional (Keyword only)
        Whether the media should be spoilered.
    
    Returns
    -------
    separator : ``Component``
    
    Raises
    ------
    TypeError
        - If a parameter's type is incorrect.
    ValueError
        - If a parameter's value is incorrect.
    """
    return Component(
        ComponentType.thumbnail_media,
        description = description,
        media = media,
        spoiler = spoiler,
    )


def create_media_gallery(
    *items,
):
    """
    Creates a new media gallery component. Can be used inside of forms.
    
    Parameters
    ----------
    *items : ``str | MediaItem``
        The media items shown on the component.
    
    Returns
    -------
    media_gallery : ``Component``
    
    Raises
    ------
    TypeError
        - If a parameter's type is incorrect.
    ValueError
        - If a parameter's value is incorrect.
    """
    return Component(
        ComponentType.media_gallery,
        items = items,
    )


def create_attachment_media(
    media,
    *,
    spoiler = ...,
):
    """
    Creates a new attachment media component. Can be used inside of forms.
    
    Parameters
    ----------
    media : ``str | MediaInfo``
        The media of the component.
    
    spoiler : `bool` Optional (Keyword only)
        Whether the media should be spoilered.
    
    Returns
    -------
    separator : ``Component``
    
    Raises
    ------
    TypeError
        - If a parameter's type is incorrect.
    ValueError
        - If a parameter's value is incorrect.
    """
    return Component(
        ComponentType.attachment_media,
        media = media,
        spoiler = spoiler,
    )


def create_separator(
    *,
    divider = ...,
    spacing_size = ...,
):
    """
    Creates a new separator component. Can be used inside of forms.
    
    Parameters
    ----------
    divider : `bool`, Optional (Keyword only)
        Whether the separator should contain a divider.
    
    spacing_size : ``int | SeparatorSpacingSize``, Optional (Keyword only)
        The separator's spacing's size.
    
    Returns
    -------
    separator : ``Component``
    
    Raises
    ------
    TypeError
        - If a parameter's type is incorrect.
    ValueError
        - If a parameter's value is incorrect.
    """
    return Component(
        ComponentType.separator,
        divider = divider,
        spacing_size = spacing_size,
    )


def create_container(
    *components,
    color = ...,
    spoiler = ...,
):
    """
    Creates a container component from the given components.
    
    Parameters
    ----------
    *components : ``Component``
        Sub components.
    
    color : ``None | Color``
        The color of the strip on the left.
    
    spoiler : `bool`, Optional (Keyword only)
        Whether the content of the component is spoilered.
    
    Returns
    -------
    container : ``Component``
    
    Raises
    ------
    TypeError
        - If a parameter's type is incorrect.
    ValueError
        - If a parameter's value is incorrect.
    """
    return Component(
        ComponentType.container,
        components = components,
        color = color,
        spoiler = spoiler,
    )


def create_label(
    label = ...,
    description = ...,
    component = ...,
):
    """
    Creates a new label component.
    
    Parameters
    ----------
    label : `None | str`, Optional
        Label of the component.
    
    description : `None | str`, Optional
        Description of the component.
    
    component : ``None | Component``, Optional
        The encapsulated component.
    
    Returns
    -------
    container : ``Component``
    
    Raises
    ------
    TypeError
        - If a parameter's type is incorrect.
    ValueError
        - If a parameter's value is incorrect.
    """
    return Component(
        ComponentType.label,
        label = label,
        description = description,
        component = component,
    )


def create_attachment_input(
    custom_id = ...,
    *,
    max_values = ...,
    min_values = ...,
    required = ...,
):
    """
    Creates a new attachment input.
    
    Parameters
    ----------
    custom_id : `None | str`, Optional
        Custom identifier to detect which component was used by the file.
    
    max_values : `int`, Optional (Keyword only)
        The maximal amount of options to upload.
        
    min_values : `int`, Optional (Keyword only)
        The minimal amount of options to upload.
    
    required : `None | bool`, Optional (Keyword only)
        Whether the field is required to be fulfilled.
    
    Returns
    -------
    attachment_input : ``Component``
    
    Raises
    ------
    TypeError
        - If a parameter's type is incorrect.
    ValueError
        - If a parameter's value is incorrect.
    """
    return Component(
        ComponentType.attachment_input,
        custom_id = custom_id,
        max_values = max_values,
        min_values = min_values,
        required = required,
    )
