#!/usr/bin/env python3

import json
import shutil
import sys
from pathlib import Path
from typing import Optional

import click

MODELS_NAMES_TO_INCLUDE_IN_PACKAEG = [
    "standard_v3_2",
]


REPO_ROOT_DIR = Path(__file__).parent.parent.parent
assert REPO_ROOT_DIR.is_dir() and (REPO_ROOT_DIR / ".git").is_dir()

ASSETS_DIR = REPO_ROOT_DIR / "assets"
assert ASSETS_DIR.is_dir()

CONTENT_TYPES_KB_PATH = ASSETS_DIR / "content_types_kb.min.json"
assert CONTENT_TYPES_KB_PATH.is_file()

ASSETS_MODELS_DIR = ASSETS_DIR / "models"
assert ASSETS_MODELS_DIR.is_dir()

PYTHON_ROOT_DIR = REPO_ROOT_DIR / "python"
assert PYTHON_ROOT_DIR.is_dir()

PYTHON_CONTENT_TYPES_KB_PATH = (
    PYTHON_ROOT_DIR / "src" / "magika" / "config" / "content_types_kb.min.json"
)

PYTHON_MODELS_DIR = PYTHON_ROOT_DIR / "src" / "magika" / "models"
assert PYTHON_MODELS_DIR.is_dir()

PYTHON_CONTENT_TYPES_LABELS_PY_PATH = (
    PYTHON_ROOT_DIR / "src" / "magika" / "types" / "content_type_label.py"
)


@click.command()
@click.option(
    "--models-names",
    "models_names_str",
    help="Comma-separated list of models names to import in the package",
)
def main(models_names_str: Optional[str]) -> None:
    if models_names_str is None:
        models_names = MODELS_NAMES_TO_INCLUDE_IN_PACKAEG
    else:
        models_names = list(map(lambda s: s.strip(), models_names_str.split(",")))

    print(f"Including these models in the package: {models_names}")

    update_content_type_kb()
    update_content_type_label_py()

    print(f"Deleting {PYTHON_MODELS_DIR}")
    shutil.rmtree(PYTHON_MODELS_DIR)
    for model_name in models_names:
        add_model_to_python_package(model_name)


def update_content_type_kb() -> None:
    print(
        f"Syncing python's content types KB: {CONTENT_TYPES_KB_PATH} => {PYTHON_CONTENT_TYPES_KB_PATH}"
    )
    PYTHON_CONTENT_TYPES_KB_PATH.parent.mkdir(parents=True, exist_ok=True)
    shutil.copy(CONTENT_TYPES_KB_PATH, PYTHON_CONTENT_TYPES_KB_PATH)


def add_model_to_python_package(model_name: str) -> None:
    assets_model_dir = ASSETS_MODELS_DIR / model_name
    if not assets_model_dir.is_dir():
        print(f'ERROR: model "{model_name} not found')
        sys.exit(1)

    python_model_dir = PYTHON_MODELS_DIR / model_name

    print(f"Adding model {assets_model_dir} => {python_model_dir}")
    shutil.copytree(assets_model_dir, python_model_dir)


CONTENT_TYPE_LABEL_SOURCE_PREFIX = """
# Copyright 2024 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


from magika.types.strenum import StrEnum

# NOTE: DO NOT EDIT --- This file is automatically generated.


# This is the list of all possible content types we know about; however, models
# support a smaller subset of them. See model's README.md for details.
class ContentTypeLabel(StrEnum):
"""


def update_content_type_label_py() -> None:
    print(f"Updating {PYTHON_CONTENT_TYPES_LABELS_PY_PATH}")

    kb = json.loads(CONTENT_TYPES_KB_PATH.read_text())

    enum_body_lines = []
    for ct_label_str in sorted(kb.keys()):
        if ct_label_str[0].isdigit():
            line = (" " * 4) + f'_{ct_label_str.upper()} = "{ct_label_str}"'
        else:
            line = (" " * 4) + f'{ct_label_str.upper()} = "{ct_label_str}"'
        enum_body_lines.append(line)

    out = (
        CONTENT_TYPE_LABEL_SOURCE_PREFIX.strip()
        + "\n"
        + "\n".join(enum_body_lines)
        + "\n"
    )
    out += (
        "\n"
        + (" " * 4)
        + (
            """
    def __repr__(self) -> str:
        return str(self)
    """.strip()
            + "\n"
        )
    )

    PYTHON_CONTENT_TYPES_LABELS_PY_PATH.write_text(out)


if __name__ == "__main__":
    main()
