import ffmpeg
import tempfile
import os
import subprocess
import urllib.request
import tarfile
import platform


class Tts:
    def __init__(self, config):
        self.piper_directory = ""
        self.install(config["service_directory"])

    def tts(self, text):
        with tempfile.NamedTemporaryFile(suffix=".wav", delete=False) as temp_file:
            output_file = temp_file.name
            piper_dir = self.piper_directory
            subprocess.run(
                [
                    os.path.join(piper_dir, "piper"),
                    "--model",
                    os.path.join(
                        piper_dir,
                        os.getenv("PIPER_VOICE_NAME", "en_US-lessac-medium.onnx"),
                    ),
                    "--output_file",
                    output_file,
                ],
                input=text,
                stdout=subprocess.PIPE,
                stderr=subprocess.PIPE,
                text=True,
            )

            # TODO: hack to format audio correctly for device
            outfile = tempfile.gettempdir() + "/" + "raw.dat"
            ffmpeg.input(temp_file.name).output(
                outfile, f="s16le", ar="16000", ac="1", loglevel="panic"
            ).run()

            return outfile

    def install(self, service_directory):
        PIPER_FOLDER_PATH = service_directory
        self.piper_directory = os.path.join(PIPER_FOLDER_PATH, "piper")
        if not os.path.isdir(
            self.piper_directory
        ):  # Check if the Piper directory exists
            os.makedirs(PIPER_FOLDER_PATH, exist_ok=True)

            # Determine OS and architecture
            OS = platform.system().lower()
            ARCH = platform.machine()
            if OS == "darwin":
                OS = "macos"
                if ARCH == "arm64":
                    ARCH = "aarch64"
                elif ARCH == "x86_64":
                    ARCH = "x64"
                else:
                    print("Piper: unsupported architecture")
                    return
            elif OS == "windows":
                if ARCH == "AMD64":
                    ARCH = "amd64"
                else:
                    print("Piper: unsupported architecture")
                    return

            PIPER_ASSETNAME = f"piper_{OS}_{ARCH}.tar.gz"
            PIPER_URL = "https://github.com/rhasspy/piper/releases/latest/download/"

            asset_url = f"{PIPER_URL}{PIPER_ASSETNAME}"

            if OS == "windows":
                asset_url = asset_url.replace(".tar.gz", ".zip")

            # Download and extract Piper
            urllib.request.urlretrieve(
                asset_url, os.path.join(PIPER_FOLDER_PATH, PIPER_ASSETNAME)
            )

            # Extract the downloaded file
            if OS == "windows":
                import zipfile

                with zipfile.ZipFile(
                    os.path.join(PIPER_FOLDER_PATH, PIPER_ASSETNAME), "r"
                ) as zip_ref:
                    zip_ref.extractall(path=PIPER_FOLDER_PATH)
            else:
                with tarfile.open(
                    os.path.join(PIPER_FOLDER_PATH, PIPER_ASSETNAME), "r:gz"
                ) as tar:
                    tar.extractall(path=PIPER_FOLDER_PATH)

            PIPER_VOICE_URL = os.getenv(
                "PIPER_VOICE_URL",
                "https://huggingface.co/rhasspy/piper-voices/resolve/main/en/en_US/lessac/medium/",
            )
            PIPER_VOICE_NAME = os.getenv("PIPER_VOICE_NAME", "en_US-lessac-medium.onnx")

            # Download voice model and its json file
            urllib.request.urlretrieve(
                f"{PIPER_VOICE_URL}{PIPER_VOICE_NAME}",
                os.path.join(self.piper_directory, PIPER_VOICE_NAME),
            )
            urllib.request.urlretrieve(
                f"{PIPER_VOICE_URL}{PIPER_VOICE_NAME}.json",
                os.path.join(self.piper_directory, f"{PIPER_VOICE_NAME}.json"),
            )

            # Additional setup for macOS
            if OS == "macos":
                if ARCH == "x64":
                    subprocess.run(
                        ["softwareupdate", "--install-rosetta", "--agree-to-license"]
                    )

                PIPER_PHONEMIZE_ASSETNAME = f"piper-phonemize_{OS}_{ARCH}.tar.gz"
                PIPER_PHONEMIZE_URL = "https://github.com/rhasspy/piper-phonemize/releases/latest/download/"
                urllib.request.urlretrieve(
                    f"{PIPER_PHONEMIZE_URL}{PIPER_PHONEMIZE_ASSETNAME}",
                    os.path.join(self.piper_directory, PIPER_PHONEMIZE_ASSETNAME),
                )

                with tarfile.open(
                    os.path.join(self.piper_directory, PIPER_PHONEMIZE_ASSETNAME),
                    "r:gz",
                ) as tar:
                    tar.extractall(path=self.piper_directory)

                PIPER_DIR = self.piper_directory
                subprocess.run(
                    [
                        "install_name_tool",
                        "-change",
                        "@rpath/libespeak-ng.1.dylib",
                        f"{PIPER_DIR}/piper-phonemize/lib/libespeak-ng.1.dylib",
                        f"{PIPER_DIR}/piper",
                    ]
                )
                subprocess.run(
                    [
                        "install_name_tool",
                        "-change",
                        "@rpath/libonnxruntime.1.14.1.dylib",
                        f"{PIPER_DIR}/piper-phonemize/lib/libonnxruntime.1.14.1.dylib",
                        f"{PIPER_DIR}/piper",
                    ]
                )
                subprocess.run(
                    [
                        "install_name_tool",
                        "-change",
                        "@rpath/libpiper_phonemize.1.dylib",
                        f"{PIPER_DIR}/piper-phonemize/lib/libpiper_phonemize.1.dylib",
                        f"{PIPER_DIR}/piper",
                    ]
                )

            print("Piper setup completed.")
        else:
            print("Piper already set up. Skipping download.")