import typing

from ..guild.emoji import Emoji

class Component:
    """
        This is the Component it used to represent a component.
    """

    def __init__(self, **data) -> None:
        self.type: int = int(
            data.get('type'))
        """The type of the component."""
        
        self.custom_id: str = data.get('custom_id')
        """The custom ID of the component."""

        self.components: typing.List["Component"] = data.get('components', [])
        """The components of the component."""

        self._raw_data = data
        """The raw data of the component."""

    @classmethod
    def form_component(cls, **data) -> "Component":
        """
            This is the form_component it used to create a component.
        """

        if data.get('type') == 2:
            return ButtonComponent(**data)

        if data.get('type') == 3:
            return SelectMenuComponent(**data)

        if data.get('type') == 4:
            return TextComponent(**data)

        return cls(**data)

    @classmethod
    def form_dict(self, data) -> typing.Dict:
        """
            This is the form_dict function.
        """

        return {
            'type': data.type,
            'components': [component.form_dict(component) for component in data.components],
        }


class ButtonComponent(Component):
    """
        This is the ButtonComponent it used to represent a button component.
    """
    type = 2

    def __init__(self, **data) -> None:
        
        self.style: int = int(
            data.get('style')) if data.get('style') else None
        """The style of the button."""

        self.label: str = data.get('label', None)
        """The label of the button."""
        
        self.emoji: "Emoji" = Emoji(None,
            data.get('emoji')) if data.get('emoji') else None
        """The emoji of the button."""

        self.url: str = data.get('url', None)
        """The URL of the button."""

        self.disabled: bool = bool(
            data.get('disabled')) if data.get('disabled') else None
        """The disabled of the button."""

        data.update({'type': self.type})
        super().__init__(**data)

    @classmethod
    def form_dict(cls, data) -> typing.Dict:
        """
            This is the form_dict function.
        """

        return {
            'type': data.type,
            'custom_id': data.custom_id,
            'style': data.style,
            'label': data.label,
            'emoji': data._raw_data.get('emoji', None),
            'url': data.url,
            'disabled': data.disabled
        }

class SelectOptionComponent(Component):
    """
        This is the SelectOptionComponent it used to represent a select option component.
    """
    type = 3

    def __init__(self, **data) -> None:
        self.label: str = data.get('label')
        """The label of the select option."""

        self.value: str = data.get('value')
        """The value of the select option."""

        self.description: str = data.get('description', None)
        """The description of the select option."""
        
        self.emoji: "Emoji" = Emoji(None, None, **data.get('emoji')) if data.get('emoji') else None
        """The emoji of the select option."""
        
        self.default: bool = bool(
            data.get('default')) if data.get('default') else None
        """The default of the select option."""

        data.update({'type': self.type})
        super().__init__(**data)

    @classmethod
    def form_dict(cls, data) -> typing.Dict:
        """
            This is the form_dict function.
        """

        return {
            'label': data.label,
            'value': data.value,
            'description': data.description,
            'emoji': data.emoji,
            'default': data.default,
        }

class SelectMenuComponent(Component):
    """
        This is the SelectMenuComponent it used to represent a select menu component.
    """
    type = 3

    def __init__(self, **data) -> None:
        if data.get('options') is dict:
            self.options: typing.List["SelectOptionComponent"] = [
                    SelectOptionComponent(**option) for option in data.get('options')]
            """The options of the select menu."""
        else:
            self.options: typing.List["SelectOptionComponent"] = data.get('options')

        self.placeholder: str = data.get('placeholder', None)
        """The placeholder of the select menu."""
        
        self.min_values: int = int(
            data.get('min_values')) if data.get('min_values') else None
        """The minimum values of the select menu."""

        self.max_values: int = int(
            data.get('max_values')) if data.get('max_values') else None
        """The maximum values of the select menu."""

        self.disabled: bool = bool(
            data.get('disabled')) if data.get('disabled') else None
        """The disabled of the select menu."""

        data.update({'type': self.type})
        super().__init__(**data)

    @classmethod
    def form_dict(cls, data) -> typing.Dict:
        """
            This is the form_dict function.
        """

        return {
            'type': data.type,
            'custom_id': data.custom_id,
            'options': [option.form_dict(option) for option in data.options],
            'placeholder': data.placeholder,
            'min_values': data.min_values,
            'max_values': data.max_values,
            'disabled': data.disabled
        }

class TextComponent(Component):
    """
        This is the TextComponent it used to represent a text component.
    """
    type = 4
    
    def __init__(self, **data) -> None:
        self.style: int = int(
            data.get('style'))
        """The style of the text."""

        self.label: str = data.get('label')
        """The label of the text."""

        self.min_length: int = int(
            data.get('min_length')) if data.get('min_length') else None
        """The minimum length of the text."""

        self.max_length: int = int(
            data.get('max_length')) if data.get('max_length') else None
        """The maximum length of the text."""

        self.required: bool = bool(
            data.get('required')) if data.get('required') else None
        """The required of the text."""

        self.value: str = data.get('value', None)
        """The value of the text."""

        self.placeholder: str = data.get('placeholder', None)
        """The placeholder of the text."""

        data.update({'type': self.type})
        super().__init__(**data)
    
    @classmethod
    def form_dict(cls, data) -> typing.Dict:
        """
            This is the form_dict function.
        """

        return {
            'type': data.type,
            'custom_id': data.custom_id,
            'style': data.style,
            'label': data.label,
            'min_length': data.min_length,
            'max_length': data.max_length,
            'required': data.required,
            'value': data.value,
            'placeholder': data.placeholder
        }