# Path: src/cutadapt/align.py
# START_WITHIN_SEQ1 = 1
# START_WITHIN_SEQ2 = 2
# STOP_WITHIN_SEQ1 = 4
# STOP_WITHIN_SEQ2 = 8
# SEMIGLOBAL = 15
#     REFERENCE_START = 1  # a prefix of the reference may be skipped at no cost
#     QUERY_START = 2  # a prefix of the query may be skipped at no cost
#     REFERENCE_END = 4  # a suffix of the reference may be skipeed at no cost
#     QUERY_STOP = 8  # a suffix of the query may be skipeed at no cost
#     SEMIGLOBAL = 15  # all of the above
# class EndSkip(IntFlag):
# def edit_distance(s: str, t: str) -> int:
# def hamming_sphere(s: str, k: int) -> Iterator[str]:
# def hamming_environment(s: str, k: int) -> Iterator[Tuple[str, int, int]]:
# def naive_edit_environment(s: str, k: int) -> Iterator[str]:
# def edit_environment(s: str, k: int) -> Iterator[Tuple[str, int, int]]:
# def slow_edit_environment(s: str, k: int) -> Iterator[Tuple[str, int, int]]:


import logging
from enum import IntFlag
from collections import defaultdict
from typing import Optional, Tuple, Sequence, Dict, Any, List, Union
from abc import ABC, abstractmethod
from .align import (
    EndSkip,
    Aligner,
    PrefixComparer,
    SuffixComparer,
    edit_environment,
    hamming_environment,
)
    @abstractmethod
    def _aligner(self):
        pass

    @abstractmethod
    def match_to(self, sequence: str):
        """
        Attempt to match this adapter to the given string.

        Return a Match instance if a match was found;
        return None if no match was found given the matching criteria (minimum
        overlap length, maximum error rate).
        """

    def __len__(self) -> int:
        return len(self.sequence)


class FrontAdapter(SingleAdapter):
    """A 5' adapter"""

    description = "regular 5'"

    def __init__(self, *args, **kwargs):
        self._force_anywhere = kwargs.pop("force_anywhere", False)
        super().__init__(*args, **kwargs)

    def descriptive_identifier(self) -> str:
        return "regular_five_prime"


# Path: src/cutadapt/align.py
# START_WITHIN_SEQ1 = 1
# START_WITHIN_SEQ2 = 2
# STOP_WITHIN_SEQ1 = 4
# STOP_WITHIN_SEQ2 = 8
# SEMIGLOBAL = 15
#     REFERENCE_START = 1  # a prefix of the reference may be skipped at no cost
#     QUERY_START = 2  # a prefix of the query may be skipped at no cost
#     REFERENCE_END = 4  # a suffix of the reference may be skipeed at no cost
#     QUERY_STOP = 8  # a suffix of the query may be skipeed at no cost
#     SEMIGLOBAL = 15  # all of the above
# class EndSkip(IntFlag):
# def edit_distance(s: str, t: str) -> int:
# def hamming_sphere(s: str, k: int) -> Iterator[str]:
# def hamming_environment(s: str, k: int) -> Iterator[Tuple[str, int, int]]:
# def naive_edit_environment(s: str, k: int) -> Iterator[str]:
# def edit_environment(s: str, k: int) -> Iterator[Tuple[str, int, int]]:
# def slow_edit_environment(s: str, k: int) -> Iterator[Tuple[str, int, int]]:


# Path: src/cutadapt/adapters.py
import logging
from enum import IntFlag
from collections import defaultdict
from typing import Optional, Tuple, Sequence, Dict, Any, List, Union
from abc import ABC, abstractmethod
from .align import (
    EndSkip,
    Aligner,
    PrefixComparer,
    SuffixComparer,
    edit_environment,
    hamming_environment,
)

    @abstractmethod
    def _aligner(self):
        pass

    @abstractmethod
    def match_to(self, sequence: str):
        """
        Attempt to match this adapter to the given string.

        Return a Match instance if a match was found;
        return None if no match was found given the matching criteria (minimum
        overlap length, maximum error rate).
        """

    def __len__(self) -> int:
        return len(self.sequence)


class FrontAdapter(SingleAdapter):
    """A 5' adapter"""

    description = "regular 5'"

    def __init__(self, *args, **kwargs):
        self._force_anywhere = kwargs.pop("force_anywhere", False)
        super().__init__(*args, **kwargs)

    def descriptive_identifier(self) -> str:
        return "regular_five_prime"


    def _aligner(self) -> Aligner: