"""
When working with regular expressions, if we define
groups, that are part of regular expressions wrapped
with parenthesis, we can also obtain the part of the
input string that fits that group. If we don't, we
can only verify, in general, if the input string fits
the regular expression or not.
"""
from yta_general_utils.programming.enum import YTAEnum as Enum
from yta_general_utils.programming.parameter_validator import PythonValidator, NumberValidator
from typing import Union

import re


class RegularExpression(Enum):
    """
    Custom YTAEnum class to hold regular expressions and to
    be able to use them directly within this class. You
    inherit this class, set your regular expressions as enum
    items and automatically they will have the 'parse' method
    to validate any string.
    """

    @staticmethod
    def is_regex(string: str) -> bool:
        """
        Check if the provided 'string' is a valid regular expression
        or not, returning True or False.
        """
        try:
            re.compile(string)
            return True
        except re.error:
            return False
        
    def parse(
        self,
        string: str
    ) -> bool:
        """
        Check this Regular Expression with the provided 'string'.
        It returns True if valid or False if not.
        """
        if not PythonValidator.is_string(string):
            raise Exception(f'The provided "string" parameter "{string}" is not a string.')
        
        return bool(re.fullmatch(self.value, string))

    def get_matching_group(
        self,
        string: str,
        group_index: int
    ) -> Union[str, None]:
        """
        Check this regular expression with the given 'string'
        and obtain the matched group in 'group_index' index.
        The regular expression must have group parts to be
        able to find these group matches.
        
        Remember that a group regular expression part is one
        wrapped in parenthesis.
        """
        if not PythonValidator.is_string(string):
            raise Exception(f'The provided "string" parameter "{string}" is not a string.')
        
        if not NumberValidator.is_positive_number(group_index, do_include_zero = True):
            raise Exception(f'The provided "group_index" parameter "{str(group_index)}" is not a positive number.')
        
        matches = re.search(self, string)

        # Giving an unvalid 'group_index' could cause an
        # unexpected behaviour
        return matches.group(group_index) if matches else None
    
# TODO: Move this to more specific regular expressions and
# maybe hold them in the library you are using them
class GeneralRegularExpression(RegularExpression):
    """
    Enum class to encapsulate useful regular
    expressions for our system and to simplify
    the way we check those regular expressions
    with some provided parameters.
    """

    FILENAME_WITH_EXTENSION = r'^[\w,\s-]+\.[a-zA-Z0-9]{2,}$'
    """
    Check if the string is a filename with a valid extension (which must
    be a common filename with a dot '.' and at least two
    alphanumeric characters).
    
    Example of a valid input: 'filename.mp3'.
    """
    YOUTUBE_VIDEO_URL = r'^(https?://)?(www\.)?(youtube\.com/watch\?v=|youtu\.be/)([a-zA-Z0-9_-]+)(&.*)?$'
    """
    Check if the string contains a valid Youtube video url.

    Example of a valid input: 'https://www.youtube.com/watch?v=OpA2ZxnRs6'
    """
    TIKTOK_SHORT_VIDEO_URL = r'^https://vm\.tiktok\.com/[a-zA-Z0-9]+$'
    """
    Check if the string contains a valid Tiktok short video url.
    This url is generated when you share a Tiktok. (?)

    Example of a valid input: 'https://vm.tiktok.com/ZGeSJ6YRA'
    """
    TIKTOK_LONG_VIDEO_URL = r'^https://www\.tiktok\.com/@[a-zA-Z0-9]+/video/\d+.*$'
    """
    Check if the string contains a valid Tiktok long video url.
    This url is the main url of a Tiktok video. (?)

    Example of a valid input: 'https://www.tiktok.com/@ahorayasabesque/video/7327001175616703777?_t=8jqq93LWqsC&_r=1'
    """
    SHORTCODE = r'\[(/?[a-zA-Z0-9-_]+)\]'
    """
    Check if the string is a valid opening or closing
    shortcode tag that can (the closing tag includes
    one slash '/' at the begining).
    """
    SNAKE_CASE = r'^[a-z0-9]+(?:_[a-z0-9]+)*$'
    """
    Check if the string is a valid snake case string.
    The snake case is something like 'this_is_snake'.
    """
    UPPER_CAMEL_CASE = r'^[A-Z][a-zA-Z0-9]*$'
    """
    Check if the string is a valid upper camel case
    string. The upper camel case string is something
    like 'ThisIsUpperCamelCase'.
    """
    LOWER_CAMEL_CASE = r'^[a-z][a-zA-Z0-9]*$'
    """
    Check if the string is a valid lower camel case
    string. The lower camel case string is something
    like 'ThisIsLowerCamelCase'.
    """