from __future__ import annotations

from pathlib import Path
from typing import TextIO

from .codecs.mlf import MLFReader
from .codecs.praat import PraatTextGridReader, PraatTextGridWriter
from .constants import DEFAULT_MLF_PRECISION, DEFAULT_TEXTGRID_PRECISION
from .documents.json_document import TextGridJsonDocument
from .domain.mlf import MLF
from .domain.models import IntervalTier, PointTier, TextGrid
from .mappers.json import json_document_to_textgrid, textgrid_to_json_document


def parse_textgrid(
    text: str,
    *,
    round_digits: int = DEFAULT_TEXTGRID_PRECISION,
    strict: bool = True,
) -> TextGrid:
    return PraatTextGridReader().read_textgrid_text(
        text,
        round_digits=round_digits,
        strict=strict,
    )


def read_textgrid(
    path: str | Path,
    *,
    round_digits: int = DEFAULT_TEXTGRID_PRECISION,
    strict: bool = True,
    encoding: str | None = None,
) -> TextGrid:
    return PraatTextGridReader().read_textgrid_file(
        path,
        round_digits=round_digits,
        strict=strict,
        encoding=encoding,
    )


def write_textgrid(
    textgrid: TextGrid,
    target: str | Path | TextIO,
    *,
    null: str | None = "",
) -> None:
    text = PraatTextGridWriter().write_textgrid(textgrid, null=null)
    if hasattr(target, "write"):
        target.write(text)
        return
    Path(target).write_text(text, encoding="utf-8")


def parse_point_tier(text: str, *, round_digits: int = DEFAULT_TEXTGRID_PRECISION) -> PointTier:
    return PraatTextGridReader().read_point_tier_text(text, round_digits=round_digits)


def read_point_tier(
    path: str | Path,
    *,
    round_digits: int = DEFAULT_TEXTGRID_PRECISION,
    encoding: str | None = None,
) -> PointTier:
    return PraatTextGridReader().read_point_tier_file(
        path,
        round_digits=round_digits,
        encoding=encoding,
    )


def parse_interval_tier(
    text: str,
    *,
    round_digits: int = DEFAULT_TEXTGRID_PRECISION,
    strict: bool = True,
) -> IntervalTier:
    return PraatTextGridReader().read_interval_tier_text(
        text,
        round_digits=round_digits,
        strict=strict,
    )


def read_interval_tier(
    path: str | Path,
    *,
    round_digits: int = DEFAULT_TEXTGRID_PRECISION,
    encoding: str | None = None,
    strict: bool = True,
) -> IntervalTier:
    return PraatTextGridReader().read_interval_tier_file(
        path,
        round_digits=round_digits,
        encoding=encoding,
        strict=strict,
    )


def read_mlf(
    path_or_text: str | Path,
    *,
    samplerate: float = 10e6,
    round_digits: int = DEFAULT_MLF_PRECISION,
) -> MLF:
    reader = MLFReader(samplerate=samplerate, round_digits=round_digits)
    if isinstance(path_or_text, Path):
        return reader.read_file(path_or_text)
    if isinstance(path_or_text, str):
        candidate = Path(path_or_text).expanduser()
        if "\n" not in path_or_text and candidate.exists():
            return reader.read_file(candidate)
        return reader.read_text(path_or_text)
    return reader.read_file(path_or_text)


def convert_textgrid_to_json_document(textgrid: TextGrid) -> TextGridJsonDocument:
    return textgrid_to_json_document(textgrid)


def convert_json_document_to_textgrid(document: TextGridJsonDocument) -> TextGrid:
    return json_document_to_textgrid(document)
