# Copyright: Ankitects Pty Ltd and contributors
# License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html

# This file is automatically generated; edit tools/genhooks.py instead.
# Please import from anki.hooks instead of this file.

# ruff: noqa: F401

from __future__ import annotations

from collections.abc import Callable, Sequence
from typing import Any

import anki
import anki.hooks
from anki.cards import Card
from anki.notes import Note

class _CardDidRenderHook:
    '''Can modify the resulting text after rendering completes.'''
    _hooks: list[Callable[["anki.template.TemplateRenderOutput", "anki.template.TemplateRenderContext"], None]] = []

    
    def append(self, callback: Callable[["anki.template.TemplateRenderOutput", "anki.template.TemplateRenderContext"], None]) -> None:
        '''(output: anki.template.TemplateRenderOutput, ctx: anki.template.TemplateRenderContext)'''
        self._hooks.append(callback)

    def remove(self, callback: Callable[["anki.template.TemplateRenderOutput", "anki.template.TemplateRenderContext"], None]) -> None:
        if callback in self._hooks:
            self._hooks.remove(callback)

    def count(self) -> int:
        return len(self._hooks)

    def __call__(self, output: anki.template.TemplateRenderOutput, ctx: anki.template.TemplateRenderContext) -> None:
        for hook in self._hooks:
            try:
                hook(output, ctx)
            except Exception:
                # if the hook fails, remove it
                self._hooks.remove(hook)
                raise



card_did_render = _CardDidRenderHook()
class _CardOdueWasInvalidHook:
    _hooks: list[Callable[[], None]] = []

    
    def append(self, callback: Callable[[], None]) -> None:
        '''()'''
        self._hooks.append(callback)

    def remove(self, callback: Callable[[], None]) -> None:
        if callback in self._hooks:
            self._hooks.remove(callback)

    def count(self) -> int:
        return len(self._hooks)

    def __call__(self) -> None:
        for hook in self._hooks:
            try:
                hook()
            except Exception:
                # if the hook fails, remove it
                self._hooks.remove(hook)
                raise



card_odue_was_invalid = _CardOdueWasInvalidHook()
class _CardWillFlushHook:
    '''Allow to change a card before it is added/updated in the database.'''
    _hooks: list[Callable[["Card"], None]] = []

    
    def append(self, callback: Callable[["Card"], None]) -> None:
        '''(card: Card)'''
        self._hooks.append(callback)

    def remove(self, callback: Callable[["Card"], None]) -> None:
        if callback in self._hooks:
            self._hooks.remove(callback)

    def count(self) -> int:
        return len(self._hooks)

    def __call__(self, card: Card) -> None:
        for hook in self._hooks:
            try:
                hook(card)
            except Exception:
                # if the hook fails, remove it
                self._hooks.remove(hook)
                raise



card_will_flush = _CardWillFlushHook()
class _DeckAddedHook:
    '''Obsolete, do not use.'''
    _hooks: list[Callable[["anki.decks.DeckDict"], None]] = []

    
    def append(self, callback: Callable[["anki.decks.DeckDict"], None]) -> None:
        '''(deck: anki.decks.DeckDict)'''
        self._hooks.append(callback)

    def remove(self, callback: Callable[["anki.decks.DeckDict"], None]) -> None:
        if callback in self._hooks:
            self._hooks.remove(callback)

    def count(self) -> int:
        return len(self._hooks)

    def __call__(self, deck: anki.decks.DeckDict) -> None:
        for hook in self._hooks:
            try:
                hook(deck)
            except Exception:
                # if the hook fails, remove it
                self._hooks.remove(hook)
                raise



deck_added = _DeckAddedHook()
class _ExportersListCreatedHook:
    _hooks: list[Callable[["list[tuple[str, Any]]"], None]] = []

    
    def append(self, callback: Callable[["list[tuple[str, Any]]"], None]) -> None:
        '''(exporters: list[tuple[str, Any]])'''
        self._hooks.append(callback)

    def remove(self, callback: Callable[["list[tuple[str, Any]]"], None]) -> None:
        if callback in self._hooks:
            self._hooks.remove(callback)

    def count(self) -> int:
        return len(self._hooks)

    def __call__(self, exporters: list[tuple[str, Any]]) -> None:
        for hook in self._hooks:
            try:
                hook(exporters)
            except Exception:
                # if the hook fails, remove it
                self._hooks.remove(hook)
                raise
        # legacy support
        anki.hooks.runHook("exportersList", exporters)



exporters_list_created = _ExportersListCreatedHook()
class _FieldFilterFilter:
    '''Allows you to define custom {{filters:..}}
        
        Your add-on can check filter_name to decide whether it should modify
        field_text or not before returning it.'''
    _hooks: list[Callable[["str", "str", "str", "anki.template.TemplateRenderContext"], str]] = []

    
    def append(self, callback: Callable[["str", "str", "str", "anki.template.TemplateRenderContext"], str]) -> None:
        '''(field_text: str, field_name: str, filter_name: str, ctx: anki.template.TemplateRenderContext)'''
        self._hooks.append(callback)

    def remove(self, callback: Callable[["str", "str", "str", "anki.template.TemplateRenderContext"], str]) -> None:
        if callback in self._hooks:
            self._hooks.remove(callback)

    def count(self) -> int:
        return len(self._hooks)

    def __call__(self, field_text: str, field_name: str, filter_name: str, ctx: anki.template.TemplateRenderContext) -> str:
        for filter in self._hooks:
            try:
                field_text = filter(field_text, field_name, filter_name, ctx)
            except Exception:
                # if the hook fails, remove it
                self._hooks.remove(filter)
                raise
        return field_text



field_filter = _FieldFilterFilter()
class _ImportingImportersHook:
    '''Allows updating the list of importers.
        The resulting list is not saved and should be changed each time the
        filter is called.
        
        NOTE: Updates to the import/export code are expected in the coming 
        months, and this hook may be replaced with another solution at that 
        time. Tracked on https://github.com/ankitects/anki/issues/1018'''
    _hooks: list[Callable[["list[tuple[str, Any]]"], None]] = []

    
    def append(self, callback: Callable[["list[tuple[str, Any]]"], None]) -> None:
        '''(importers: list[tuple[str, Any]])'''
        self._hooks.append(callback)

    def remove(self, callback: Callable[["list[tuple[str, Any]]"], None]) -> None:
        if callback in self._hooks:
            self._hooks.remove(callback)

    def count(self) -> int:
        return len(self._hooks)

    def __call__(self, importers: list[tuple[str, Any]]) -> None:
        for hook in self._hooks:
            try:
                hook(importers)
            except Exception:
                # if the hook fails, remove it
                self._hooks.remove(hook)
                raise



importing_importers = _ImportingImportersHook()
class _LegacyExportProgressHook:
    '''Temporary hook used in transition to new import/export code.'''
    _hooks: list[Callable[["str"], None]] = []

    
    def append(self, callback: Callable[["str"], None]) -> None:
        '''(progress: str)'''
        self._hooks.append(callback)

    def remove(self, callback: Callable[["str"], None]) -> None:
        if callback in self._hooks:
            self._hooks.remove(callback)

    def count(self) -> int:
        return len(self._hooks)

    def __call__(self, progress: str) -> None:
        for hook in self._hooks:
            try:
                hook(progress)
            except Exception:
                # if the hook fails, remove it
                self._hooks.remove(hook)
                raise



legacy_export_progress = _LegacyExportProgressHook()
class _MediaFileFilterFilter:
    '''Allows manipulating the file path that media will be read from'''
    _hooks: list[Callable[["str"], str]] = []

    
    def append(self, callback: Callable[["str"], str]) -> None:
        '''(txt: str)'''
        self._hooks.append(callback)

    def remove(self, callback: Callable[["str"], str]) -> None:
        if callback in self._hooks:
            self._hooks.remove(callback)

    def count(self) -> int:
        return len(self._hooks)

    def __call__(self, txt: str) -> str:
        for filter in self._hooks:
            try:
                txt = filter(txt)
            except Exception:
                # if the hook fails, remove it
                self._hooks.remove(filter)
                raise
        return txt



media_file_filter = _MediaFileFilterFilter()
class _MediaFilesDidExportHook:
    '''Only used by legacy .apkg exporter. Will be deprecated in the future.'''
    _hooks: list[Callable[["int"], None]] = []

    
    def append(self, callback: Callable[["int"], None]) -> None:
        '''(count: int)'''
        self._hooks.append(callback)

    def remove(self, callback: Callable[["int"], None]) -> None:
        if callback in self._hooks:
            self._hooks.remove(callback)

    def count(self) -> int:
        return len(self._hooks)

    def __call__(self, count: int) -> None:
        for hook in self._hooks:
            try:
                hook(count)
            except Exception:
                # if the hook fails, remove it
                self._hooks.remove(hook)
                raise



media_files_did_export = _MediaFilesDidExportHook()
class _NoteTypeAddedHook:
    '''Obsolete, do not use.'''
    _hooks: list[Callable[["anki.models.NotetypeDict"], None]] = []

    
    def append(self, callback: Callable[["anki.models.NotetypeDict"], None]) -> None:
        '''(notetype: anki.models.NotetypeDict)'''
        self._hooks.append(callback)

    def remove(self, callback: Callable[["anki.models.NotetypeDict"], None]) -> None:
        if callback in self._hooks:
            self._hooks.remove(callback)

    def count(self) -> int:
        return len(self._hooks)

    def __call__(self, notetype: anki.models.NotetypeDict) -> None:
        for hook in self._hooks:
            try:
                hook(notetype)
            except Exception:
                # if the hook fails, remove it
                self._hooks.remove(hook)
                raise



note_type_added = _NoteTypeAddedHook()
class _NoteWillBeAddedHook:
    '''Allows modifying a note before it's added to the collection.

        This hook may be called both when users use the Add screen, and when
        add-ons like AnkiConnect add notes. It is not called when importing. If
        you wish to alter the Add screen, use gui_hooks.add_cards_will_add_note
        instead.'''
    _hooks: list[Callable[["anki.collection.Collection", "anki.notes.Note", "anki.decks.DeckId"], None]] = []

    
    def append(self, callback: Callable[["anki.collection.Collection", "anki.notes.Note", "anki.decks.DeckId"], None]) -> None:
        '''(col: anki.collection.Collection, note: anki.notes.Note, deck_id: anki.decks.DeckId)'''
        self._hooks.append(callback)

    def remove(self, callback: Callable[["anki.collection.Collection", "anki.notes.Note", "anki.decks.DeckId"], None]) -> None:
        if callback in self._hooks:
            self._hooks.remove(callback)

    def count(self) -> int:
        return len(self._hooks)

    def __call__(self, col: anki.collection.Collection, note: anki.notes.Note, deck_id: anki.decks.DeckId) -> None:
        for hook in self._hooks:
            try:
                hook(col, note, deck_id)
            except Exception:
                # if the hook fails, remove it
                self._hooks.remove(hook)
                raise



note_will_be_added = _NoteWillBeAddedHook()
class _NoteWillFlushHook:
    '''Allow to change a note before it is added/updated in the database.'''
    _hooks: list[Callable[["Note"], None]] = []

    
    def append(self, callback: Callable[["Note"], None]) -> None:
        '''(note: Note)'''
        self._hooks.append(callback)

    def remove(self, callback: Callable[["Note"], None]) -> None:
        if callback in self._hooks:
            self._hooks.remove(callback)

    def count(self) -> int:
        return len(self._hooks)

    def __call__(self, note: Note) -> None:
        for hook in self._hooks:
            try:
                hook(note)
            except Exception:
                # if the hook fails, remove it
                self._hooks.remove(hook)
                raise



note_will_flush = _NoteWillFlushHook()
class _NotesWillBeDeletedHook:
    _hooks: list[Callable[["anki.collection.Collection", "Sequence[anki.notes.NoteId]"], None]] = []

    
    def append(self, callback: Callable[["anki.collection.Collection", "Sequence[anki.notes.NoteId]"], None]) -> None:
        '''(col: anki.collection.Collection, ids: Sequence[anki.notes.NoteId])'''
        self._hooks.append(callback)

    def remove(self, callback: Callable[["anki.collection.Collection", "Sequence[anki.notes.NoteId]"], None]) -> None:
        if callback in self._hooks:
            self._hooks.remove(callback)

    def count(self) -> int:
        return len(self._hooks)

    def __call__(self, col: anki.collection.Collection, ids: Sequence[anki.notes.NoteId]) -> None:
        for hook in self._hooks:
            try:
                hook(col, ids)
            except Exception:
                # if the hook fails, remove it
                self._hooks.remove(hook)
                raise
        # legacy support
        anki.hooks.runHook("remNotes", col, ids)



notes_will_be_deleted = _NotesWillBeDeletedHook()
class _SchemaWillChangeFilter:
    _hooks: list[Callable[["bool"], bool]] = []

    
    def append(self, callback: Callable[["bool"], bool]) -> None:
        '''(proceed: bool)'''
        self._hooks.append(callback)

    def remove(self, callback: Callable[["bool"], bool]) -> None:
        if callback in self._hooks:
            self._hooks.remove(callback)

    def count(self) -> int:
        return len(self._hooks)

    def __call__(self, proceed: bool) -> bool:
        for filter in self._hooks:
            try:
                proceed = filter(proceed)
            except Exception:
                # if the hook fails, remove it
                self._hooks.remove(filter)
                raise
        return proceed



schema_will_change = _SchemaWillChangeFilter()
class _SyncProgressDidChangeHook:
    '''Obsolete, do not use.'''
    _hooks: list[Callable[["str"], None]] = []

    
    def append(self, callback: Callable[["str"], None]) -> None:
        '''(msg: str)'''
        self._hooks.append(callback)

    def remove(self, callback: Callable[["str"], None]) -> None:
        if callback in self._hooks:
            self._hooks.remove(callback)

    def count(self) -> int:
        return len(self._hooks)

    def __call__(self, msg: str) -> None:
        for hook in self._hooks:
            try:
                hook(msg)
            except Exception:
                # if the hook fails, remove it
                self._hooks.remove(hook)
                raise



sync_progress_did_change = _SyncProgressDidChangeHook()
class _SyncStageDidChangeHook:
    '''Obsolete, do not use.'''
    _hooks: list[Callable[["str"], None]] = []

    
    def append(self, callback: Callable[["str"], None]) -> None:
        '''(stage: str)'''
        self._hooks.append(callback)

    def remove(self, callback: Callable[["str"], None]) -> None:
        if callback in self._hooks:
            self._hooks.remove(callback)

    def count(self) -> int:
        return len(self._hooks)

    def __call__(self, stage: str) -> None:
        for hook in self._hooks:
            try:
                hook(stage)
            except Exception:
                # if the hook fails, remove it
                self._hooks.remove(hook)
                raise



sync_stage_did_change = _SyncStageDidChangeHook()

