from statistics import mean


class KeySmash:
    """A class for calculating metrics to indicate key smashing behavior in a text.

    Key smashing is the act of typing on a keyboard in a rapid and uncontrolled manner,
    often resulting in a series of random characters being entered into a document or text field.
    """

    def __init__(self):
        self.char_sets = {
            "vowels": "aeiouáéíóúãõ",
            "consonants": "bcdfghjklmnñpqrstvwxyz",
            "special_characters": "!@#$%^¨|'\"&*()_+:;~`´]}{[}ºª=-.¿¡",
        }

    def calculate_char_frequency_metric(self, text):
        """
        Calculate the Char Frequency Metric.

        Parameters
        ----------
        text : str
            The text to use for the calculation.

        Returns
        -------
        float
            Char Frequency Metric.

        Examples
        --------
        >>> calculate_char_frequency_metric("PUENTECILLA KM. 1.7")
        1.121212121212121
        >>> calculate_char_frequency_metric("ASDASD XXXX")
        3.0
        """
        word_results = []

        for w in text.split(" "):
            char_count = []
            if w and len(w) > 0:
                for e in set(w):
                    char_count.append(w.count(e) ** 2)
                word_results.append(sum(char_count) / len(w))

        if word_results == 0 or len(word_results) == 0:
            return 0
        else:
            return mean(word_results)

    def calculate_irregular_sequence_metric(self, text, opt):
        """
        Calculate the Irregular Sequence Metric.

        Parameters
        ----------
        text : str
            The text to use for the calculation.
        opt : str
            The type of characters to consider for the calculation,
            can be one of 'vowels', 'consonants', or 'special_characters'.

        Returns
        -------
        float
            Irregular Sequence Metric.

        Examples
        --------
        >>> calculate_irregular_sequence_metric("PUENTECILLA KM. 1.7", "vowels")
        0.21052631578947367
        >>> calculate_irregular_sequence_metric("ASDASD XXXX", "consonants")
        2.1818181818181817
        >>> calculate_irregular_sequence_metric("!@#$% ASDFGHJKL", "special_characters")
        1.5625
        """
        count_sequence = 1
        sequence_regex = []

        text = str(text).lower()
        opt = self.char_sets[opt]

        for i in range(len(text) - 1):
            if text[i] in opt and text[i + 1] in opt:
                count_sequence = count_sequence + 1
            else:
                if count_sequence != 1:
                    sequence_regex.append(count_sequence**2)
                    count_sequence = 1

        if count_sequence != 1:
            sequence_regex.append(count_sequence**2)

        return sum(sequence_regex) / len(text)

    def calculate_number_count_metric(self, text):
        """
        Calculate the Number Count Metric.

        Parameters
        ----------
        text : str
            The text field to use for the calculation.

        Returns
        -------
        float
            Number Count Metric.

        Examples
        --------
        >>> calculate_number_count_metric("ABC 123 !@#")
        0.0
        >>> calculate_number_count_metric("ABC123 !@#")
        0.9
        """
        text_list = text.split()
        calc_num_line = 0

        if text_list:
            for word in text_list:
                if any(char.isdigit() for char in word) and any(
                    not char.isdigit() for char in word
                ):
                    num = len([char for char in word if char.isdigit()])
                    calc_num = num**2
                    calc_num_line += calc_num

            return calc_num_line / len(" ".join(text_list))
        return 0
