#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from typing import Self, Any, Optional
from Interfaces.FormatModuleInterface import FormatModuleInterface
from Utils.Patterns import RE
from Utils.Check import Check
from Utils.Utils import Utils

class SelectFormat:

    def __init__(self:Self, 
        format:FormatModuleInterface, 
        options:Optional[dict[str, Any|None]] = None
    ) -> None:
        self.format:FormatModuleInterface = format
        self.capitalize:bool = bool(options and options.get("capitalized"))

    def __get_separator_and_items(self:Self, i:int, inputs:str|list[Any|None]) -> tuple[tuple[int, int], str, list[str]]:

        range:tuple[int, int]
        separator:str
        original_items:list[str]

        separator, original_items = (
            (lambda _, range, separator, options:(
                tuple(int(value) for value in range.split("-")), separator, str(options).split("|")
            ))(*RE.SELECT_MODE_SPLIT.match(inputs).groups()) if Check.is_string(inputs) else 
            inputs if Check.is_array(inputs) else 
        (None, None, None))

        return range, separator, self.format.get_list(i, original_items)

    def get(self:Self, 
        i:int, 
        inputs:str|list[Any|None], 
        shared:dict[str, Any|None] = {}, 
        fragments:list[str] = []
    ) -> str:
        
        range:tuple[int, int]
        separator:str
        items:list[str]

        range, separator, items = self.__get_separator_and_items(i, inputs)
        k = Utils.get_random(*range)

        if not k:
            return ""
        
        l:int = len(items)
        results:str

        if l < 2:
            results = "".join(items)
        else:

            Utils.randomize_array(items)
            items = items[:k]
            l = len(items)

            results = (
                items[0] if l < 2 else 
            ", ".join(items[:l - 1]) + (
                " " if not separator else 
                " " + separator.strip() + " " if RE.IS_SEPARATOR.match(separator) else
            separator) + items[l - 1])

        results = self.format.execute(i, results, shared, fragments)

        return RE.CAPITAL_CASE.sub(lambda matches:(
            matches.group(1).upper()
        ), results) if self.capitalize else results
    
    def check(self:Self, 
        i:int, 
        string:str, 
        inputs:str|list[Any|None], 
        shared:dict[str, Any|None] = {}, 
        fragments:list[str] = []
    ) -> int:
        
        minimum:int
        maximum:int
        separator:str
        items:list[str]
        l:int

        (minimum, maximum), separator, items = self.__get_separator_and_items(i, inputs)

        return self.format.check_select(i, string, (
            (minimum, maximum), separator, items
        ), shared, fragments)
        
