from typing import Optional

from mimesis.builtins.base import BaseSpecProvider
from mimesis.enums import Gender
from mimesis.utils import pull


class RussiaSpecProvider(BaseSpecProvider):
    """Specific data for Russian language"""

    def __init__(self):
        super().__init__()
        self._data = pull('builtin.json', 'ru')

    class Meta:
        name = 'russia_provider'

    def generate_sentence(self) -> str:
        """Generate sentence from the parts.

        :return: Sentence.
        """
        sentences = self._data['sentence']
        sentence = [
            self.random.choice(sentences[k]) for k
            in ('head', 'p1', 'p2', 'tail')
        ]
        return '{0} {1} {2} {3}'.format(*sentence)

    def patronymic(self, gender: Optional[Gender] = None) -> str:
        """Generate random patronymic name.

        :param gender: Gender of person.
        :type gender: str or int
        :return: Patronymic name.

        :Example:
            Алексеевна.
        """
        gender = self._validate_enum(gender, Gender)
        patronymics = self._data['patronymic'][gender]
        return self.random.choice(patronymics)

    def passport_series(self, year: int = None) -> str:
        """Generate random series of passport.

        :param year: Year of manufacture.
        :type year: int or None
        :return: Series.

        :Example:
            02 15.
        """
        if not year:
            year = self.random.randint(10, 18)

        region = self.random.randint(1, 99)
        return '{:02d} {}'.format(region, year)

    def passport_number(self) -> int:
        """Generate random passport number.

        :return: Number.

        :Example:
            560430
        """
        return self.random.randint(
            100000, 999999)

    def series_and_number(self) -> str:
        """Generate a random passport number and series.

        :return: Series and number.

        :Example:
            57 16 805199.
        """

        return '{}{}'.format(
            self.passport_series(),
            self.passport_number(),
        )

    def snils(self) -> str:
        """Generate Individual insurance account number (SNILS).
        This method does not generate SNILS using algorithm and
        it's mean that SNILS generated by this method can be invalid.

        :return: SNILS.

        :Example:
            451-952-540-41.
        """
        mask = '###-###-###-##'
        return self.random.custom_code(mask=mask)
