from typing import (
    Tuple,
    Any,
    Collection,
    Iterable,
    Iterator,
    List,
    Callable,
    Set,
    Union,
    TypeVar,
    overload,
)
from enum import Enum

from pikepdf.models.image import PdfInlineImage

T = TypeVar('T', bound=Object)


def _new_operator(op: str) -> Object:
    ...


def _Null() -> Any:
    ...


def _encode(handle: Any) -> Object:
    ...


def _new_array(arg0: Iterable) -> Object:
    ...


def _new_boolean(arg0: bool) -> Object:
    ...


def _new_dictionary(arg0: dict) -> Object:
    ...


def _new_integer(arg0: int) -> Object:
    ...


def _new_name(arg0: str) -> Object:
    ...


@overload
def _new_real(arg0: str) -> Object:
    ...


@overload
def _new_real(value: float, places: int = ...) -> Object:
    ...


@overload
def _new_real(*args, **kwargs) -> Any:
    ...


def _new_stream(arg0: Pdf, arg1: bytes) -> Object:
    ...


def _new_string(s: Union[str, bytes]) -> Object:
    ...


def _new_string_utf8(s: str) -> Object:
    ...


def _roundtrip(obj: Any) -> Any:
    ...


def _test_file_not_found(*args, **kwargs) -> Any:
    ...


def get_decimal_precision() -> int:
    ...


def pdf_doc_to_utf8(pdfdoc: bytes) -> str:
    ...


def qpdf_version() -> str:
    ...


def set_access_default_mmap(mmap: bool) -> bool:
    ...


def set_decimal_precision(prec: int) -> int:
    ...


def unparse(obj: Any) -> bytes:
    ...


def utf8_to_pdf_doc(utf8: str, unknown: bytes) -> Tuple[bool, bytes]:
    ...


class AccessMode(Enum):
    default: int = ...
    mmap: int = ...
    mmap_only: int = ...
    stream: int = ...


class Annotation:
    def __init__(self, arg0: Object) -> None:
        ...

    def get_appearance_stream(self, which: Object, state: str = ...) -> Object:
        ...

    def get_page_content_for_appearance(
        self,
        name: Object,
        rotate: int,
        required_flags: int = ...,
        forbidden_flags: int = ...,
    ) -> str:
        ...

    @property
    def appearance_dict(self) -> Object:
        ...

    @property
    def appearance_state(self) -> str:
        ...

    @property
    def flags(self) -> int:
        ...

    @property
    def subtype(self) -> str:
        ...


class Buffer:
    def __init__(self, *args, **kwargs) -> None:
        ...


class EncryptionMethod(Enum):
    none: int = ...
    unknown: int = ...
    rc4: int = ...
    aes: int = ...
    aesv3: int = ...


class Object:
    _ipython_key_completions_: Any = ...
    _repr_mimebundle_: Any = ...
    emplace: Any = ...
    write: Any = ...

    def __init__(self, *args, **kwargs) -> None:
        ...

    def _inline_image_raw_bytes(self) -> bytes:
        ...

    def _parse_page_contents(self, callbacks: Callable) -> None:
        ...

    def _parse_page_contents_grouped(
        self, whitelist: str
    ) -> List[Tuple[Collection[Union[Object, 'PdfInlineImage']], Operator]]:
        ...

    def _parse_stream(self, *args, **kwargs) -> Any:
        ...

    def _parse_stream_grouped(self, *args, **kwargs) -> Any:
        ...

    def _write(self, data: bytes, filter: object, decode_parms: object) -> None:
        ...

    def append(self, pyitem: Object) -> None:
        ...

    def as_dict(self) -> _ObjectMapping:
        ...

    def as_list(self) -> _ObjectList:
        ...

    def extend(self, arg0: Iterable[Object]) -> None:
        ...

    @overload
    def get(self, key: str, default: object = ...) -> object:
        ...

    @overload
    def get(key, default=...) -> Any:
        ...

    @overload
    def get(self, key: Object, default: object = ...) -> object:
        ...

    @overload
    def get(*args, **kwargs) -> Any:
        ...

    def get_raw_stream_buffer(self) -> Buffer:
        ...

    def get_stream_buffer(self, decode_level: StreamDecodeLevel = ...) -> Buffer:
        ...

    def is_owned_by(self, possible_owner: Pdf) -> bool:
        ...

    def items(self) -> Iterable[Tuple[str, Object]]:
        ...

    def keys(self) -> Set[str]:
        ...

    def page_contents_add(self, contents: Object, prepend: bool = ...) -> None:
        ...

    def page_contents_coalesce(self) -> None:
        ...

    @staticmethod
    def parse(stream: bytes, description: str = ...) -> Object:
        ...

    def read_bytes(self, decode_level: StreamDecodeLevel = ...) -> bytes:
        ...

    def read_raw_bytes(self) -> bytes:
        ...

    def same_owner_as(self, other: Object) -> bool:
        ...

    def to_json(self, dereference: bool = ...) -> bytes:
        ...

    def unparse(self, resolved: bool = ...) -> bytes:
        ...

    def wrap_in_array(self) -> Object:
        ...

    def __bytes__(self) -> bytes:
        ...

    @overload
    def __contains__(self, arg0: Object) -> bool:
        ...

    @overload
    def __contains__(self, arg0: str) -> bool:
        ...

    @overload
    def __contains__(*args, **kwargs) -> Any:
        ...

    def __copy__(self) -> Object:
        ...

    def __delattr__(self, arg0: str) -> None:
        ...

    @overload
    def __delitem__(self, arg0: str) -> None:
        ...

    @overload
    def __delitem__(self, arg0: Object) -> None:
        ...

    @overload
    def __delitem__(self, arg0: int) -> None:
        ...

    @overload
    def __delitem__(*args, **kwargs) -> Any:
        ...

    def __dir__(self) -> list:
        ...

    def __eq__(self, other: Any) -> bool:
        ...

    def __getattr__(self, arg0: str) -> Object:
        ...

    @overload
    def __getitem__(self, arg0: str) -> Object:
        ...

    @overload
    def __getitem__(self, arg0: Object) -> Object:
        ...

    @overload
    def __getitem__(self, arg0: int) -> Object:
        ...

    @overload
    def __getitem__(*args, **kwargs) -> Any:
        ...

    def __hash__(self) -> int:
        ...

    def __iter__(self) -> Iterable[Object]:
        ...

    def __len__(self) -> int:
        ...

    def __setattr__(self, arg0: str, arg1: object) -> None:
        ...

    @overload
    def __setitem__(self, arg0: str, arg1: Object) -> None:
        ...

    @overload
    def __setitem__(self, arg0: Object, arg1: Object) -> None:
        ...

    @overload
    def __setitem__(self, arg0: str, arg1: object) -> None:
        ...

    @overload
    def __setitem__(self, arg0: Object, arg1: object) -> None:
        ...

    @overload
    def __setitem__(self, arg0: int, arg1: Object) -> None:
        ...

    @overload
    def __setitem__(self, arg0: int, arg1: object) -> None:
        ...

    @overload
    def __setitem__(*args, **kwargs) -> Any:
        ...

    @property
    def _objgen(self) -> Tuple[int, int]:
        ...

    @property
    def _type_code(self) -> ObjectType:
        ...

    @property
    def _type_name(self) -> str:
        ...

    @property
    def images(self) -> _ObjectMapping:
        ...

    @property
    def is_indirect(self) -> bool:
        ...

    @property
    def is_rectangle(self) -> bool:
        ...

    @property
    def objgen(self) -> Tuple[int, int]:
        ...

    @property
    def stream_dict(self) -> Object:
        ...

    @stream_dict.setter
    def stream_dict(self, val: Object) -> None:
        ...


class Operator(Object):
    ...


class ObjectStreamMode(Enum):
    disable: Any = ...
    generate: Any = ...
    preserve: Any = ...


class ObjectType(Enum):
    array: Any = ...
    boolean: Any = ...
    dictionary: Any = ...
    inlineimage: Any = ...
    integer: Any = ...
    name: Any = ...
    null: Any = ...
    operator: Any = ...
    real: Any = ...
    reserved: Any = ...
    stream: Any = ...
    string: Any = ...
    uninitialized: Any = ...


class Page:
    _repr_mimebundle_: Any = ...

    def __init__(self, arg0: Object) -> None:
        ...

    def _get_cropbox(self, arg0: bool) -> Object:
        ...

    def _get_mediabox(self, arg0: bool) -> Object:
        ...

    def _get_trimbox(self, arg0: bool) -> Object:
        ...

    def add_content_token_filter(self, tf) -> None:
        ...

    def as_form_xobject(self, handle_transformations: bool = ...) -> Object:
        ...

    def contents_coalesce(self) -> None:
        ...

    def externalize_inline_images(self, min_size: int = ...) -> None:
        ...

    def get_filtered_contents(self, tf: TokenFilter) -> bytes:
        ...

    def parse_contents(self, arg0: StreamParser) -> None:
        ...

    def remove_unreferenced_resources(self) -> None:
        ...

    def rotate(self, angle: int, relative: bool) -> None:
        ...

    @property
    def _images(self) -> _ObjectMapping:
        ...

    @property
    def cropbox(self) -> Any:
        ...

    @cropbox.setter
    def cropbox(self, val: Any) -> None:
        ...

    @property
    def mediabox(self) -> Any:
        ...

    @mediabox.setter
    def mediabox(self, val: Any) -> None:
        ...

    @property
    def obj(self) -> Object:
        ...

    @property
    def trimbox(self) -> Any:
        ...

    @trimbox.setter
    def trimbox(self, val: Any) -> None:
        ...


class PageList:
    def __init__(self, *args, **kwargs) -> None:
        ...

    def append(self, page: object) -> None:
        ...

    @overload
    def extend(self, other: PageList) -> None:
        ...

    @overload
    def extend(self, iterable: Iterable[Object]) -> None:
        ...

    def insert(self, index: int, obj: object) -> None:
        ...

    def p(self, pnum: int) -> Object:
        ...

    def remove(self, **kwargs) -> None:
        ...

    def reverse(self) -> None:
        ...

    @overload
    def __delitem__(self, arg0: int) -> None:
        ...

    @overload
    def __delitem__(self, arg0: slice) -> None:
        ...

    @overload
    def __delitem__(*args, **kwargs) -> Any:
        ...

    @overload
    def __getitem__(self, arg0: int) -> Object:
        ...

    @overload
    def __getitem__(self, arg0: slice) -> list:
        ...

    @overload
    def __getitem__(*args, **kwargs) -> Any:
        ...

    def __iter__(self) -> PageList:
        ...

    def __len__(self) -> int:
        ...

    def __next__(self) -> Object:
        ...

    @overload
    def __setitem__(self, arg0: int, arg1: Object) -> None:
        ...

    @overload
    def __setitem__(self, arg0: slice, arg1: Iterable[Object]) -> None:
        ...

    @overload
    def __setitem__(*args, **kwargs) -> Any:
        ...


class PasswordError(Exception):
    ...


class ForeignObjectError(Exception):
    ...


class Pdf:
    _attach: Any = ...
    _repr_mimebundle_: Any = ...
    add_blank_page: Any = ...
    check: Any = ...
    close: Any = ...
    make_stream: Any = ...
    open: Any = ...
    open_metadata: Any = ...
    open_outline: Any = ...
    save: Any = ...
    __enter__: Any = ...
    __exit__: Any = ...

    def __init__(self, *args, **kwargs) -> None:
        ...

    def _add_page(self, page: Object, first: bool = ...) -> None:
        ...

    def _add_page_at(self, arg0: Object, arg1: bool, arg2: Object) -> None:
        ...

    def _decode_all_streams_and_discard(self) -> None:
        ...

    def _get_object_id(self, arg0: int, arg1: int) -> Object:
        ...

    def _open(self, *args, **kwargs) -> Any:
        ...

    def _process(self, arg0: str, arg1: bytes) -> None:
        ...

    def _remove_page(self, arg0: Object) -> None:
        ...

    def _replace_object(self, arg0: int, arg1: int, arg2: Object) -> None:
        ...

    def _save(
        self,
        filename: object,
        static_id: bool = ...,
        preserve_pdfa: bool = ...,
        min_version: object = ...,
        force_version: object = ...,
        fix_metadata_version: bool = ...,
        compress_streams: bool = ...,
        stream_decode_level: object = ...,
        object_stream_mode: ObjectStreamMode = ...,
        normalize_content: bool = ...,
        linearize: bool = ...,
        qdf: bool = ...,
        progress: object = ...,
        encryption: object = ...,
        samefile_check: bool = ...,
    ) -> None:
        ...

    def _swap_objects(self, arg0: Tuple[int, int], arg1: Tuple[int, int]) -> None:
        ...

    def check_linearization(self, stream: object = ...) -> bool:
        ...

    def copy_foreign(self, h: Object) -> Object:
        ...

    @overload
    def get_object(self, objgen: Tuple[int, int]) -> Object:
        ...

    @overload
    def get_object(self, objid: int, gen: int) -> Object:
        ...

    @overload
    def get_object(*args, **kwargs) -> Any:
        ...

    def get_warnings(self) -> list:
        ...

    @overload
    def make_indirect(self, h: T) -> T:
        ...

    @overload
    def make_indirect(self, obj: object) -> Object:
        ...

    def new(self, *args, **kwargs) -> Any:
        ...

    def remove_unreferenced_resources(self) -> None:
        ...

    def show_xref_table(self) -> None:
        ...

    @property
    def Root(self) -> Object:
        ...

    @property
    def _allow_accessibility(self) -> bool:
        ...

    @property
    def _allow_extract(self) -> bool:
        ...

    @property
    def _allow_modify_all(self) -> bool:
        ...

    @property
    def _allow_modify_annotation(self) -> bool:
        ...

    @property
    def _allow_modify_assembly(self) -> bool:
        ...

    @property
    def _allow_modify_form(self) -> bool:
        ...

    @property
    def _allow_modify_other(self) -> bool:
        ...

    @property
    def _allow_print_highres(self) -> bool:
        ...

    @property
    def _allow_print_lowres(self) -> bool:
        ...

    @property
    def _encryption_data(self) -> dict:
        ...

    @property
    def _pages(self) -> Any:
        ...

    @property
    def allow(self) -> Any:
        ...

    @property
    def docinfo(self) -> Object:
        ...

    @docinfo.setter
    def docinfo(self, val: Object) -> None:
        ...

    @property
    def encryption(self) -> Any:
        ...

    @property
    def extension_level(self) -> int:
        ...

    @property
    def filename(self) -> str:
        ...

    @property
    def is_encrypted(self) -> bool:
        ...

    @property
    def is_linearized(self) -> bool:
        ...

    @property
    def objects(self) -> Any:
        ...

    @property
    def pages(self) -> PageList:
        ...

    @property
    def pdf_version(self) -> str:
        ...

    @property
    def root(self) -> Object:
        ...

    @property
    def trailer(self) -> Object:
        ...


class PdfError(Exception):
    ...


class StreamDecodeLevel(Enum):
    all: Any = ...
    generalized: Any = ...
    none: Any = ...
    specialized: Any = ...


class StreamParser:
    def __init__(self) -> None:
        ...

    def handle_eof(self) -> None:
        ...

    def handle_object(self, arg0: Object) -> None:
        ...


class Token:
    def __init__(self, arg0: TokenType, arg1: bytes) -> None:
        ...

    def __eq__(self, other: Any) -> bool:
        ...

    @property
    def error_msg(self) -> str:
        ...

    @property
    def raw_value(self) -> bytes:
        ...

    @property
    def type_(self) -> TokenType:
        ...

    @property
    def value(self) -> str:
        ...


class TokenFilter(_QPDFTokenFilter):
    def __init__(self) -> None:
        ...

    def handle_token(self, token: Token = ...) -> object:
        ...


class TokenType(Enum):
    array_close: Any = ...
    array_open: Any = ...
    bad: Any = ...
    bool: Any = ...
    brace_close: Any = ...
    brace_open: Any = ...
    comment: Any = ...
    dict_close: Any = ...
    dict_open: Any = ...
    eof: Any = ...
    inline_image: Any = ...
    integer: Any = ...
    name: Any = ...
    null: Any = ...
    real: Any = ...
    space: Any = ...
    string: Any = ...
    word: Any = ...


class _ObjectList:
    @overload
    def __init__(self) -> None:
        ...

    @overload
    def __init__(self, arg0: _ObjectList) -> None:
        ...

    @overload
    def __init__(self, arg0: Iterable) -> None:
        ...

    @overload
    def __init__(*args, **kwargs) -> None:
        ...

    def append(self, x: Object) -> None:
        ...

    def clear(self) -> None:
        ...

    def count(self, x: Object) -> int:
        ...

    @overload
    def extend(self, L: _ObjectList) -> None:
        ...

    @overload
    def extend(self, L: Iterable[Object]) -> None:
        ...

    def insert(self, i: int, x: Object) -> None:
        ...

    @overload
    def pop(self) -> Object:
        ...

    @overload
    def pop(self, i: int) -> Object:
        ...

    @overload
    def pop(*args, **kwargs) -> Any:
        ...

    def remove(self, x: Object) -> None:
        ...

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

    def __contains__(self, x: Object) -> bool:
        ...

    @overload
    def __delitem__(self, arg0: int) -> None:
        ...

    @overload
    def __delitem__(self, arg0: slice) -> None:
        ...

    @overload
    def __delitem__(*args, **kwargs) -> Any:
        ...

    def __eq__(self, other: Any) -> bool:
        ...

    @overload
    def __getitem__(self, s: slice) -> _ObjectList:
        ...

    @overload
    def __getitem__(self, arg0: int) -> Object:
        ...

    @overload
    def __getitem__(*args, **kwargs) -> Any:
        ...

    def __iter__(self) -> Iterator[Object]:
        ...

    def __len__(self) -> int:
        ...

    def __ne__(self, other: Any) -> bool:
        ...

    @overload
    def __setitem__(self, arg0: int, arg1: Object) -> None:
        ...

    @overload
    def __setitem__(self, arg0: slice, arg1: _ObjectList) -> None:
        ...

    @overload
    def __setitem__(*args, **kwargs) -> Any:
        ...


class _ObjectMapping:
    get: Any = ...
    keys: Any = ...
    values: Any = ...
    __contains__: Any = ...

    def __init__(self) -> None:
        ...

    def items(self) -> Iterator:
        ...

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

    def __delitem__(self, arg0: str) -> None:
        ...

    def __getitem__(self, arg0: str) -> Object:
        ...

    def __iter__(self) -> Iterator:
        ...

    def __len__(self) -> int:
        ...

    def __setitem__(self, arg0: str, arg1: Object) -> None:
        ...


class _QPDFTokenFilter:
    def __init__(self, *args, **kwargs) -> None:
        ...
