"""api.py

Interface for managuing and procesing files
"""

# Standard Library
from pathlib import Path

# Local
from . import DATA_FOLDER
from .anki_generation import (
    output_anki_dictation,
    output_anki_dictionary,
    output_anki_phrase,
)
from .constants import (
    DICTATION_TYPE,
    DICT_TYPE,
    INPUT,
    LANGUAGES,
    OUTPUT,
    PHRASES_TYPE,
    RESOURCES,
)
from .proccessor import (
    dictation_process,
    dictionary_pre_process,
    dictionary_process,
    translator_process,
)
from .utility import CCCEDICT, TRANS, TTS, ProcessFile

# interface


def get_data_folder() -> Path:
    """Utility function, return the data folder"""
    return DATA_FOLDER


def get_output_folder() -> Path:
    """Utility function, return the OUTPUT folder"""
    return OUTPUT


def get_resources_folder() -> Path:
    """Utility function, return the RESOURCES folder"""
    return RESOURCES


def list_input_files(search_path: Path = Path()) -> list[Path]:
    """Return a list of files relative to the INPUT path"""
    level = INPUT / search_path
    return [path.relative_to(INPUT) for path in level.glob("*")]


def is_file(file_path: Path) -> bool:
    """Check if a relative path is a file"""
    return (INPUT / file_path).is_file()


def read_input_file(file_path: Path) -> str:
    """Reads an input file"""
    return (INPUT / file_path).open(encoding="utf8", newline="\n").read()


def read_dictionary_file(process_file: ProcessFile, language_id: str) -> str:
    """Reads an dictionary resource file"""
    process_file.language_id = language_id
    return process_file.dictionary_resource_file.open(
        encoding="utf8", newline="\n"
    ).read()


def select_file(file_path: Path) -> ProcessFile:
    """Given a relative path from `list_input_files`, return a ProcessFile"""
    if (INPUT / file_path).is_file():
        return ProcessFile(file_path)
    else:
        raise ValueError(f"{file_path} is not a file")


def create_folder(file_path: Path) -> ProcessFile:
    """Creates a folder in a file_path"""
    input_folder = INPUT / file_path
    if input_folder.exists():
        raise ValueError(f"{file_path} already exists")
    else:
        input_folder.mkdir(exist_ok=True, parents=True)
        return ProcessFile(input_folder)


def delete_folder(file_path: Path):
    """Delete an empty folder in file_path"""
    input_folder = INPUT / file_path
    if input_folder.exists():
        if any(Path("some/path/here").iterdir()):
            raise ValueError(f"{file_path} has files inside")
        else:
            input_folder.rmdir()
    else:
        raise ValueError(f"{file_path} doesn't exists")


def delete_file(file_path: Path):
    """Deletes a file in a file_path"""
    input_file = INPUT / file_path
    if input_file.if_file():
        input_file.unlink()
    else:
        raise ValueError(f"{file_path} doesn't exists")


def list_file_resources(file_path: ProcessFile):
    """Returns a list of a file_path resources files"""
    return [file_path.resources.glob("*")]


def analize_input_files(search_path: Path = Path()) -> dict[str, list[Path]]:
    """Analaizes a path file, and returns input, resources and output files"""
    data = {
        "input": [],
        "resources": [],
        "output": [],
    }
    if search_path is None:
        return data
    input_path = INPUT / search_path
    if input_path.is_file():
        process_file = ProcessFile(search_path)
        res_path = process_file.resources
        outputs_path = process_file.out_folder
        data["input"] = [search_path]
        data["resources"] = [path.relative_to(RESOURCES) for path in res_path.glob("*")]
        data["output"] = [
            path.relative_to(OUTPUT)
            for path in outputs_path.glob(f"{process_file.input_file.stem}*")
        ]
    elif input_path.exists():
        res_path = RESOURCES / search_path
        outputs_path = OUTPUT / search_path
        data["input"] = [path.relative_to(INPUT) for path in input_path.glob("*")]
        data["resources"] = [path.relative_to(RESOURCES) for path in res_path.glob("*")]
        data["output"] = [path.relative_to(OUTPUT) for path in outputs_path.glob("*")]
    return data


def create_input_file(
    name: str, file_type: str, text: str, sub_folder: Path = Path()
) -> ProcessFile:
    """Creates an input file, with a name and a type form the available ones,
    writes a text to it, if a sub_folder is given,
    it is created and the file placed inside.
    returns the relative path for future processing

    valid file_types: ".phrases", ".dictionary" ".dictation"
    """
    if file_type not in (PHRASES_TYPE, DICT_TYPE, DICTATION_TYPE):
        raise ValueError(
            f"file_type {file_type} not in {(PHRASES_TYPE, DICT_TYPE, DICTATION_TYPE)}"
        )
    filename = f"{name}{file_type}.txt"
    relative = sub_folder / filename
    # write file
    file_path = INPUT / relative
    file_path.parent.mkdir(exist_ok=True, parents=True)
    file_path.write_text(text, encoding="utf8", newline="\n")
    # create process_file for future
    process_file = ProcessFile(relative)
    return process_file


def write_input_file(process_file: ProcessFile, text: str):
    """Write an input file"""
    with process_file.absolute_input_file.open(
        "w", encoding="utf8", newline="\n"
    ) as file:
        for line in text.split("\n"):
            line = line.strip()
            if line:
                file.write(f"{line}\n")


def write_resource_file(process_file: ProcessFile, language_id: str, text: str):
    """Write a resource file"""
    process_file.language_id = language_id
    with process_file.dictionary_resource_file.open(
        "w", encoding="utf8", newline="\n"
    ) as file:
        for line in text.split("\n"):
            line = line.strip()
            if line:
                file.write(f"{line}\n")


def pre_process_a_dictionary_file(process_file: ProcessFile, language_id: str):
    """From a input_file, a language_id and an output type, process a file"""
    process_file.language_id = language_id
    TRANS.create_translator(LANGUAGES.EN, language_id)
    CCCEDICT.create_cedict(language_id)
    with process_file.absolute_input_file.open(
        "r", encoding="utf8", newline="\n"
    ) as file:
        words_list = [word.strip() for word in file.readlines() if word]
    dictionary_pre_process(words_list, process_file)


def process_a_dictionary_file(process_file: ProcessFile, language_id: str) -> Path:
    """Process a dictionary file"""
    TTS.create_tts()
    process_file.language_id = language_id
    results = dictionary_process(process_file)
    return output_anki_dictionary(process_file, results)


def process_a_dictation_file(process_file: ProcessFile, language_id: str) -> Path:
    """Process a dictation file"""
    TTS.create_tts()
    TRANS.create_translator(LANGUAGES.CN, language_id)
    process_file.language_id = language_id
    with process_file.absolute_input_file.open(
        "r", encoding="utf8", newline="\n"
    ) as file:
        text_lines = [line.strip() for line in file.read().split("。")]
    results = dictation_process(text_lines, process_file)
    return output_anki_dictation(process_file, results)


def process_a_phrases_file(process_file: ProcessFile, language_id: str) -> Path:
    """Process a phrases file"""
    process_file.language_id = language_id
    TTS.create_tts()
    TRANS.create_translator(LANGUAGES.CN, language_id)
    with process_file.absolute_input_file.open(
        "r", encoding="utf8", newline="\n"
    ) as file:
        text_lines = [line.strip() for line in file.readlines()]
    results = translator_process(text_lines, process_file)
    return output_anki_phrase(process_file, results)
