from __future__ import annotations

import importlib.resources
import pathlib
import shutil
import subprocess
import tempfile
import typing

from .. import utilities

EXTENSION = ".gif"


def run(
    input: pathlib.Path,
    output: pathlib.Path,
    begin: int,
    end: int,
    parameters: dict[str, typing.Any],
):
    frametime = int(
        round(
            (end - begin) / utilities.timecode(parameters["forward_duration"]) * 20000.0
        )
    )
    tau = int(round(parameters["tau_to_frametime_ratio"] * frametime))
    print(f"{begin=}, {end=}, {frametime=}, {tau=}")
    with tempfile.TemporaryDirectory() as temporary_directory_string:
        temporary_directory = pathlib.Path(temporary_directory_string)
        base_frames = temporary_directory / "base_frames"
        base_frames.mkdir(exist_ok=True)
        es_to_frames_arguments = [
            str(utilities.asset_path("es_to_frames")),
            f"--input={input}",
            f"--output={base_frames}",
            f"--begin={begin}",
            f"--end={end}",
            f"--frametime={frametime}",
            f"--scale={parameters['scale']}",
            f"--style={parameters['style']}",
            f"--tau={tau}",
            f"--oncolor={parameters['on_color']}",
            f"--offcolor={parameters['off_color']}",
            f"--idlecolor={parameters['idle_color']}",
            f"--cumulative-ratio={parameters['cumulative_ratio']}",
        ]
        if "lambda_max" in parameters:
            es_to_frames_arguments.append(f"--lambda-max={parameters['lambda_max']}")
        if parameters["timecode"]:
            es_to_frames_arguments.append("--add-timecode")
        subprocess.run(
            es_to_frames_arguments,
            check=True,
        )
        sorted_frames = temporary_directory / "sorted_frames"
        sorted_frames.mkdir(exist_ok=True)
        if parameters["rewind"]:
            paths: list[pathlib.Path] = []
            for path in sorted(base_frames.iterdir()):
                if path.suffix == ".ppm":
                    paths.append(path)
            selected_paths: list[pathlib.Path] = []
            if len(paths) >= round(parameters["tau_to_frametime_ratio"]) + 2:
                for index, path in enumerate(paths):
                    if (
                        index >= round(parameters["tau_to_frametime_ratio"])
                        and index % 2 == 1
                    ):
                        selected_paths.append(path)
            else:
                selected_paths = paths
            output_index = 0
            for path in selected_paths:
                shutil.copyfile(path, sorted_frames / f"{output_index:>06d}.ppm")
                output_index += 1
            for path in reversed(selected_paths[1:-1]):
                path.replace(sorted_frames / f"{output_index:>06d}.ppm")
                output_index += 1
        else:
            output_index = 0
            for path in sorted(base_frames.iterdir()):
                if path.suffix == ".ppm":
                    shutil.copyfile(path, sorted_frames / f"{output_index:>06d}.ppm")
                    output_index += 1
        subprocess.run(
            [
                parameters["ffmpeg"],
                "-hide_banner",
                "-loglevel",
                "error",
                "-i",
                str(sorted_frames / "%06d.ppm"),
                "-framerate",
                "25",
                "-filter_complex",
                "[0:v] split [a][b];[a] palettegen=reserve_transparent=true [p];[b][p] paletteuse=dither=none",
                "-loop",
                "0",
                "-f",
                "gif",
                "-y",
                str(output),
            ],
            check=True,
        )
