from typing import Any, Callable, Dict, List, NamedTuple, Optional, Sequence, Tuple, Type, Union

from django.core.paginator import Paginator, SupportsCount, SupportsLen
from django.db.models import QuerySet
from django.http import HttpRequest
from django.views import View
from rest_framework.request import Request

def _positive_int(integer_string: str, strict: bool = ..., cutoff: Optional[int] = ...) -> int: ...
def _divide_with_ceil(a: int, b: int) -> int: ...
def _get_displayed_page_numbers(current: int, final: int) -> List[Optional[int]]: ...
def _get_page_links(
    page_numbers: Sequence[Optional[int]], current: int, url_func: Callable[[int], str]
) -> List[PageLink]: ...
def _reverse_ordering(ordering_tuple: Sequence[str]) -> Tuple[str, ...]: ...

class Cursor(NamedTuple):
    offset: int
    reverse: bool
    position: Optional[str]

class PageLink(NamedTuple):
    url: Optional[str]
    number: Optional[int]
    is_active: bool
    is_break: bool

PAGE_BREAK: PageLink = ...

class BasePagination(object):
    display_page_controls: bool = ...
    def paginate_queryset(self, queryset: QuerySet, request: HttpRequest, view: Optional[View] = ...): ...
    def get_paginated_response(self, data: Any) -> Optional[List[Any]]: ...
    def to_html(self) -> str: ...
    def get_results(self, data: Dict[str, Any]) -> Any: ...
    def get_schema_fields(self, view: View) -> List[Any]: ...

class PageNumberPagination(BasePagination):
    page_size: int = ...

    django_paginator_class: Type[Paginator] = ...
    page_query_param: str = ...
    page_query_description: str = ...

    page_size_query_param: Optional[str] = ...
    page_size_query_description: str = ...
    max_page_size: Optional[int] = ...

    last_page_strings: Sequence[str] = ...

    template: str = ...

    invalid_page_message: str = ...
    def get_page_size(self, request: Request) -> int: ...
    def get_next_link(self) -> Optional[str]: ...
    def get_previous_link(self) -> Optional[str]: ...
    def get_html_context(self) -> Dict[str, Any]: ...

class LimitOffsetPagination(BasePagination):
    default_limit: int = ...
    limit_query_param: str = ...
    limit_query_description: str = ...
    offset_query_param: str = ...
    offset_query_description: str = ...
    max_limit: Optional[int] = ...
    template: str = ...
    def get_limit(self, request: Request) -> int: ...
    def get_offset(self, request: Request) -> int: ...
    def get_next_link(self) -> Optional[str]: ...
    def get_previous_link(self) -> Optional[str]: ...
    def get_html_context(self) -> Dict[str, Any]: ...
    def get_count(self, queryset: Union[SupportsCount, SupportsLen]) -> int: ...

class CursorPagination(BasePagination):
    cursor_query_param: str = ...
    cursor_query_description: str = ...
    page_size: int = ...
    invalid_cursor_message: str = ...
    ordering: str = ...
    template: str = ...
    page_size_query_param: Optional[str] = ...
    page_size_query_description: str = ...
    max_page_size: Optional[int] = ...
    offset_cutoff: int = ...
    def get_page_size(self, request: Request) -> Optional[int]: ...
    def get_next_link(self) -> Optional[str]: ...
    def get_previous_link(self) -> Optional[str]: ...
    def get_ordering(self, request: Request, queryset: QuerySet, view: View) -> Tuple[str, ...]: ...
    def decode_cursor(self, request: Request) -> Optional[Cursor]: ...
    def encode_cursor(self, cursor: Cursor) -> str: ...
    def _get_position_from_instance(self, instance: Any, ordering: Sequence[str]) -> str: ...
    def get_html_context(self) -> Dict[str, str]: ...
