import enum
from pathlib import Path
from typing import List

from pysam import AlignedSegment
from pysam import FastxRecord

from pybwa.libbwaindex import BwaIndex

# class syntax
@enum.unique
class BwaMemMode(enum.Enum):
    """The read type for overriding multiple options."""

    PACBIO = enum.auto()
    ONT2D = enum.auto()
    INTRACTG = enum.auto()

class BwaMemOptions:
    def __init__(
        self,
        min_seed_len: int = 19,
        mode: BwaMemMode | None = None,
        band_width: int = 100,
        match_score: int = 1,
        mismatch_penalty: int = 4,
        minimum_score: int = 30,
        unpaired_penalty: int = 17,
        skip_pairing: bool = False,
        output_all_for_fragments: bool = False,
        interleaved_paired_end: bool = False,
        short_split_as_secondary: bool = False,
        skip_mate_rescue: bool = False,
        soft_clip_supplementary: bool = False,
        with_xr_tag: bool = False,
        query_coord_as_primary: bool = False,
        keep_mapq_for_supplementary: bool = False,
        with_xb_tag: bool = False,
        max_occurrences: int = 500,
        off_diagonal_x_dropoff: int = 100,
        ignore_alternate_contigs: bool = False,
        internal_seed_split_factor: float = 1.5,
        drop_chain_fraction: float = 0.50,
        max_mate_rescue_rounds: int = 50,
        min_seeded_bases_in_chain: int = 0,
        seed_occurrence_in_3rd_round: int = 20,
        xa_max_hits: int | tuple[int, int] = (5, 200),
        xa_drop_ratio: float = 0.80,
        gap_open_penalty: int | tuple[int, int] = 6,
        gap_extension_penalty: int | tuple[int, int] = 1,
        clipping_penalty: int | tuple[int, int] = 5,
        threads: int = 1,
        chunk_size: int = 10_000_000,
    ) -> None: ...
    _finalized: bool
    _ignore_alt: bool
    _mode: BwaMemMode | None
    @property
    def finalized(self) -> bool: ...
    @property
    def min_seed_len(self) -> int: ...
    @min_seed_len.setter
    def min_seed_len(self, value: int) -> None: ...
    @property
    def mode(self) -> BwaMemMode | None: ...
    @mode.setter
    def mode(self, value: BwaMemMode | None) -> None: ...
    @property
    def band_width(self) -> int: ...
    @band_width.setter
    def band_width(self, value: int) -> None: ...
    @property
    def match_score(self) -> int: ...
    @match_score.setter
    def match_score(self, value: int) -> None: ...
    @property
    def mismatch_penalty(self) -> int: ...
    @mismatch_penalty.setter
    def mismatch_penalty(self, value: int) -> None: ...
    @property
    def minimum_score(self) -> int: ...
    @minimum_score.setter
    def minimum_score(self, value: int) -> None: ...
    @property
    def unpaired_penalty(self) -> int: ...
    @unpaired_penalty.setter
    def unpaired_penalty(self, value: int) -> None: ...
    @property
    def n_threads(self) -> int: ...
    @n_threads.setter
    def n_threads(self, value: int) -> None: ...
    @property
    def skip_pairing(self) -> bool: ...
    @skip_pairing.setter
    def skip_pairing(self, value: bool) -> None: ...
    @property
    def output_all_for_fragments(self) -> bool: ...
    @output_all_for_fragments.setter
    def output_all_for_fragments(self, value: bool) -> None: ...
    @property
    def interleaved_paired_end(self) -> bool: ...
    @interleaved_paired_end.setter
    def interleaved_paired_end(self, value: bool) -> None: ...
    @property
    def short_split_as_secondary(self) -> bool: ...
    @short_split_as_secondary.setter
    def short_split_as_secondary(self, value: bool) -> None: ...
    @property
    def skip_mate_rescue(self) -> bool: ...
    @skip_mate_rescue.setter
    def skip_mate_rescue(self, value: bool) -> None: ...
    @property
    def soft_clip_supplementary(self) -> bool: ...
    @soft_clip_supplementary.setter
    def soft_clip_supplementary(self, value: bool) -> None: ...
    @property
    def with_xr_tag(self) -> bool: ...
    @with_xr_tag.setter
    def with_xr_tag(self, value: bool) -> None: ...
    @property
    def query_coord_as_primary(self) -> bool: ...
    @query_coord_as_primary.setter
    def query_coord_as_primary(self, value: bool) -> None: ...
    @property
    def keep_mapq_for_supplementary(self) -> bool: ...
    @keep_mapq_for_supplementary.setter
    def keep_mapq_for_supplementary(self, value: bool) -> None: ...
    @property
    def with_xb_tag(self) -> bool: ...
    @with_xb_tag.setter
    def with_xb_tag(self, value: bool) -> None: ...
    @property
    def max_occurrences(self) -> int: ...
    @max_occurrences.setter
    def max_occurrences(self, value: int) -> None: ...
    @property
    def off_diagonal_x_dropoff(self) -> int: ...
    @off_diagonal_x_dropoff.setter
    def off_diagonal_x_dropoff(self, value: int) -> None: ...
    @property
    def ignore_alternate_contigs(self) -> bool: ...
    @ignore_alternate_contigs.setter
    def ignore_alternate_contigs(self, value: bool) -> None: ...
    @property
    def internal_seed_split_factor(self) -> float: ...
    @internal_seed_split_factor.setter
    def internal_seed_split_factor(self, value: float) -> None: ...
    @property
    def drop_chain_fraction(self) -> float: ...
    @drop_chain_fraction.setter
    def drop_chain_fraction(self, value: float) -> None: ...
    @property
    def max_mate_rescue_rounds(self) -> int: ...
    @max_mate_rescue_rounds.setter
    def max_mate_rescue_rounds(self, value: int) -> None: ...
    @property
    def min_seeded_bases_in_chain(self) -> int: ...
    @min_seeded_bases_in_chain.setter
    def min_seeded_bases_in_chain(self, value: int) -> None: ...
    @property
    def seed_occurrence_in_3rd_round(self) -> int: ...
    @seed_occurrence_in_3rd_round.setter
    def seed_occurrence_in_3rd_round(self, value: int) -> None: ...
    @property
    def xa_max_hits(self) -> int | tuple[int, int]: ...
    @xa_max_hits.setter
    def xa_max_hits(self, value: int | tuple[int, int]) -> None: ...
    @property
    def xa_drop_ratio(self) -> float: ...
    @xa_drop_ratio.setter
    def xa_drop_ratio(self, value: float) -> None: ...
    @property
    def gap_open_penalty(self) -> int | tuple[int, int]: ...
    @gap_open_penalty.setter
    def gap_open_penalty(self, value: int | tuple[int, int]) -> None: ...
    @property
    def gap_extension_penalty(self) -> int | tuple[int, int]: ...
    @gap_extension_penalty.setter
    def gap_extension_penalty(self, value: int | tuple[int, int]) -> None: ...
    @property
    def clipping_penalty(self) -> int | tuple[int, int]: ...
    @clipping_penalty.setter
    def clipping_penalty(self, value: int | tuple[int, int]) -> None: ...
    @property
    def threads(self) -> int: ...
    @threads.setter
    def threads(self, value: int) -> None: ...
    @property
    def chunk_size(self) -> int: ...
    @chunk_size.setter
    def chunk_size(self, value: int) -> None: ...
    def finalize(self, copy: bool = False) -> BwaMemOptions: ...

class BwaMem:
    _index: BwaIndex
    def __init__(self, prefix: str | Path | None = None, index: BwaIndex | None = None) -> None: ...
    def align(
        self, queries: List[FastxRecord] | List[str], opt: BwaMemOptions | None = None
    ) -> List[List[AlignedSegment]]: ...

def _set_bwa_mem_verbosity(level: int) -> bool: ...
def _assert_mem_opt_are_the_same() -> None: ...
def _call_mem_opt_when_not_finalized() -> None: ...
