# SPDX-License-Identifier: MIT
# Copyright (C) 2022 Max Bachmann

from __future__ import annotations

from typing import Iterator, List, Tuple, Union

_AnyOpList = Union[
    List[Union[Editop, Tuple[str, int, int]]],
    List[Union[Opcode, Tuple[str, int, int, int, int]]],
]

class MatchingBlock:
    a: int
    b: int
    size: int

    def __init__(self, a: int, b: int, size: int): ...
    def __len__(self) -> int: ...
    def __eq__(self, other: object) -> bool: ...
    def __getitem__(self, i: int) -> int: ...
    def __iter__(self) -> Iterator[int]: ...
    def __repr__(self) -> str: ...

class Editop:
    tag: str
    src_pos: int
    dest_pos: int

    def __init__(self, tag: str, src_pos: int, dest_pos: int): ...
    def __len__(self) -> int: ...
    def __eq__(self, other: object) -> bool: ...
    def __getitem__(self, i: int) -> int | str: ...
    def __iter__(self) -> Iterator[int | str]: ...
    def __repr__(self) -> str: ...

class Editops:
    _src_len: int
    _dest_len: int
    _editops: list[Editop]

    def __init__(
        self,
        editops: _AnyOpList | None = None,
        src_len: int = 0,
        dest_len: int = 0,
    ): ...
    @classmethod
    def from_opcodes(cls, opcodes: Opcodes) -> Editops: ...
    def as_matching_blocks(self) -> list[MatchingBlock]: ...
    def as_list(self) -> list[Editop]: ...
    def copy(self) -> Editops: ...
    def inverse(self) -> Editops: ...
    def remove_subsequence(self, subsequence: Editops) -> None: ...
    def apply(self, source_string: str, destination_string: str) -> str: ...
    @property
    def src_len(self) -> int: ...
    @src_len.setter
    def src_len(self, value: int) -> None: ...
    @property
    def dest_len(self) -> int: ...
    @dest_len.setter
    def dest_len(self, value: int) -> None: ...
    def __eq__(self, other: object) -> bool: ...
    def __len__(self) -> int: ...
    def __delitem__(self, key: int | slice) -> None: ...
    def __getitem__(self, key: int | slice) -> Editops | Editop: ...
    def __iter__(self) -> Iterator[Editop]: ...
    def __repr__(self) -> str: ...

class Opcode:
    tag: str
    src_start: int
    src_end: int
    dest_start: int
    dest_end: int

    def __init__(self, tag: str, src_start: int, src_end: int, dest_start: int, dest_end: int): ...
    def __len__(self) -> int: ...
    def __eq__(self, other: object) -> bool: ...
    def __getitem__(self, i: int) -> int | str: ...
    def __iter__(self) -> Iterator[int | str]: ...

class Opcodes:
    _src_len: int
    _dest_len: int
    _opcodes: list[Opcode]

    def __init__(
        self,
        opcodes: _AnyOpList | None = None,
        src_len: int = 0,
        dest_len: int = 0,
    ): ...
    @classmethod
    def from_editops(cls, editops: Editops) -> Opcodes: ...
    def as_editops(self) -> Editops: ...
    def as_matching_blocks(self) -> list[MatchingBlock]: ...
    def as_list(self) -> list[Opcode]: ...
    def copy(self) -> Opcodes: ...
    def inverse(self) -> Opcodes: ...
    def apply(self, source_string: str, destination_string: str) -> str: ...
    @property
    def src_len(self) -> int: ...
    @src_len.setter
    def src_len(self, value: int) -> None: ...
    @property
    def dest_len(self) -> int: ...
    @dest_len.setter
    def dest_len(self, value: int) -> None: ...
    def __eq__(self, other: object) -> bool: ...
    def __len__(self) -> int: ...
    def __getitem__(self, key: int) -> Opcode: ...
    def __iter__(self) -> Iterator[Opcode]: ...
    def __repr__(self) -> str: ...

class ScoreAlignment:
    score: int | float
    src_start: int
    src_end: int
    dest_start: int
    dest_end: int

    def __init__(
        self,
        score: int | float,
        src_start: int,
        src_end: int,
        dest_start: int,
        dest_end: int,
    ): ...
    def __len__(self) -> int: ...
    def __eq__(self, other: object) -> bool: ...
    def __getitem__(self, i: int) -> int | float: ...
    def __iter__(self) -> Iterator[int | float]: ...
    def __repr__(self) -> str: ...
