from typing import List, Type, TypeVar, Tuple
from enum import Enum

from torch import Tensor

T = TypeVar("T")

class MissingSegmentError(Exception): ...

class IpaSegmenter:
    ipa_segments: List[str]

    def __init__(self, ipa_segments: List[str]) -> None: ...
    def segment(self, transcription: str, include_missing: bool = False) -> List[str]: ...
    def segment_checked(self, transcription: str) -> List[str]: ...
    def segment_words(self, transcriped_words: List[str], include_missing: bool = False) -> List[str]: ...
    def segment_words_checked(self, transcriped_words: List[str]) -> List[str]: ...

class PropertyWeighting:
    def __init__(self, insertion_cost: float, deletion_cost: float, property_table: Tensor): ...
    def levensthein_operations(self, string_a: List, string_b: List) -> Tuple[List[Tuple[Action, int]], float]: ...
    def levensthein_statistics(self, string_a: List, string_b: List) -> EditStatistics: ...
    def levensthein_matrix(self, string_a: List, string_b: List) -> Tensor: ...

class Action(Enum):
    INSERTION = 1
    DELETION = 2
    SUBSTITUTION = 3

    @staticmethod
    def from_int(integer: int) -> Action: ...
    def __int__(self) -> int: ...

EditStatisticsCls = TypeVar("EditStatisticsCls", bound="EditStatistics")

class EditStatistics:
    insertions: int
    deletions: int
    substitutions: int
    correct: int

    def __init__(self, insertions: int, deletions: int, substitutions: int, correct: int) -> None: ...
    @classmethod
    def zeros(cls: Type[EditStatisticsCls]) -> EditStatisticsCls: ...
    def word_error_rate(self) -> float: ...
    def __add__(self, other: EditStatistics) -> EditStatistics: ...
    def __iadd__(self, other: EditStatistics) -> EditStatistics: ...

LevenstheinOperations = List[Tuple[Action, int, int]]

def levensthein(string_a: List, string_b: List) -> int: ...
def levensthein_operations(string_a: List, string_b: List) -> Tuple[LevenstheinOperations, float]: ...
def levensthein_statistics(string_a: List, string_b: List) -> EditStatistics: ...
def levensthein_matrix(string_a: List, string_b: List) -> Tensor: ...
def to_substitutions(
    string_a: List, string_b: List, operations: LevenstheinOperations
) -> List[Tuple[Action, str, str]]: ...
