"""Provides a random choice from items in a sequence."""
import typing as t

from mimesis.providers.base import BaseProvider

__all__ = ["Choice"]


class Choice(BaseProvider):
    """Class for generating a random choice from items in a sequence."""

    class Meta:
        """Class for metadata."""

        name: t.Final[str] = "choice"

    def __call__(
        self,
        items: t.Optional[t.Sequence[t.Any]],
        length: int = 0,
        unique: bool = False,
    ) -> t.Union[t.Sequence[t.Any], t.Any]:
        """Generate a randomly-chosen sequence or bare element from a sequence.

        Provide elements randomly chosen from the elements in a sequence
        **items**, where when **length** is specified the random choices are
        contained in a sequence of the same type of length **length**,
        otherwise a single uncontained element is chosen. If **unique** is set
        to True, constrain a returned sequence to contain only unique elements.

        :param items: Non-empty sequence (list, tuple or string) of elements.
        :param length: Length of sequence (number of elements) to provide.
        :param unique: If True, ensures provided elements are unique.
        :return: Sequence or uncontained element randomly chosen from items.
        :raises TypeError: For non-sequence items or non-integer length.
        :raises ValueError: If negative length or insufficient unique elements.

        >>> from mimesis import Choice
        >>> choice = Choice()

        >>> choice(items=['a', 'b', 'c'])
        'c'
        >>> choice(items=['a', 'b', 'c'], length=1)
        ['a']
        >>> choice(items='abc', length=2)
        'ba'
        >>> choice(items=('a', 'b', 'c'), length=5)
        ('c', 'a', 'a', 'b', 'c')
        >>> choice(items='aabbbccccddddd', length=4, unique=True)
        'cdba'
        """

        if not isinstance(items, t.Sequence):
            raise TypeError("**items** must be non-empty sequence.")

        if not items:
            raise ValueError("**items** must be a non-empty sequence.")

        if length < 0:
            raise ValueError("**length** should be a positive integer.")

        if length == 0:
            return self.random.choice(items)

        data: t.List[str] = []
        if unique and len(set(items)) < length:  # avoid an infinite while loop
            raise ValueError(
                "There are not enough unique elements in "
                "**items** to provide the specified **number**."
            )
        while len(data) < length:
            item = self.random.choice(items)
            if (unique and item not in data) or not unique:
                data.append(item)

        if isinstance(items, list):
            return data
        elif isinstance(items, tuple):
            return tuple(data)
        return "".join(data)

@@ -2234,39 +2234,8 @@
 s)%0A%0A
-        data: t.List%5Bstr%5D = %5B%5D%0A
     
@@ -2285,36 +2285,20 @@
   # 
-avoid an infinite while loop
+Sanity check
 %0A   
@@ -2474,171 +2474,166 @@
     
-while len(data) %3C length:%0A            item = self.random.choice(items)%0A            if (unique and item not in data) or not unique:%0A                data.append(item
+if unique:%0A            data: t.List%5Bstr%5D = self.random.sample(list(set(items)), k=length)%0A        else:%0A            data = self.random.choices(items, k=length
 )%0A%0A 

Improve random sampling performance. (#1271)