"""Provides an immutable sequence view class."""

from __future__ import annotations

from sys import maxsize
from typing import TYPE_CHECKING, Generic, Iterator, Sequence, TypeVar, overload

T = TypeVar("T")


class ImmutableSequenceView(Generic[T]):
    """Class to wrap a sequence of some sort, but not allow modification."""

    def __init__(self, wrap: Sequence[T]) -> None:
        """Initialise the immutable sequence.

        Args:
            wrap: The sequence being wrapped.
        """
        self._wrap = wrap

    if TYPE_CHECKING:

        @overload
        def __getitem__(self, index: int) -> T: ...

        @overload
        def __getitem__(self, index: slice) -> ImmutableSequenceView[T]: ...

    def __getitem__(self, index: int | slice) -> T | ImmutableSequenceView[T]:
        return (
            self._wrap[index]
            if isinstance(index, int)
            else ImmutableSequenceView[T](self._wrap[index])
        )

    def __iter__(self) -> Iterator[T]:
        return iter(self._wrap)

    def __len__(self) -> int:
        return len(self._wrap)

    def __length_hint__(self) -> int:
        return len(self)

    def __bool__(self) -> bool:
        return bool(self._wrap)

    def __contains__(self, item: T) -> bool:
        return item in self._wrap

    def index(self, item: T, start: int = 0, stop: int = maxsize) -> int:
        """Return the index of the given item.

        Args:
            item: The item to find in the sequence.
            start: Optional start location.
            stop: Optional stop location.

        Returns:
            The index of the item in the sequence.

        Raises:
            ValueError: If the item is not in the sequence.
        """
        return self._wrap.index(item, start, stop)

    def __reversed__(self) -> Iterator[T]:
        return reversed(self._wrap)
