# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you 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.

"""Build helper: stages the native library and binary-distribution legal files."""

import os
import platform
import shutil

from setuptools import Distribution, setup
from setuptools.command.build_py import build_py
from wheel.bdist_wheel import bdist_wheel

LEGAL_FILES = ("LICENSE", "NOTICE", "LICENSE-binary")
LEGAL_SOURCE_FILES = {
    "LICENSE": "LICENSE",
    "NOTICE": "NOTICE",
    "LICENSE-binary": "LICENSE-binary-ffi",
}


def _lib_name():
    system = platform.system()
    if system == "Darwin":
        return "libpaimon_vindex_ffi.dylib"
    if system == "Windows":
        return "paimon_vindex_ffi.dll"
    return "libpaimon_vindex_ffi.so"


def _find_native_lib():
    here = os.path.dirname(os.path.abspath(__file__))
    lib = _lib_name()

    env_path = os.environ.get("PAIMON_VINDEX_LIB_PATH")
    if env_path:
        if os.path.isfile(env_path):
            return env_path
        candidate = os.path.join(env_path, lib)
        if os.path.isfile(candidate):
            return candidate

    for profile in ["release", "debug"]:
        candidate = os.path.join(here, "..", "target", profile, lib)
        if os.path.isfile(candidate):
            return candidate

    return None


def _stage_legal_files(destination_dir):
    here = os.path.dirname(os.path.abspath(__file__))
    staged = []

    for name in LEGAL_FILES:
        source = os.path.join(here, "..", LEGAL_SOURCE_FILES[name])
        destination = os.path.join(destination_dir, name)
        if not os.path.isfile(source):
            raise RuntimeError(f"required binary legal file is missing: {source}")
        if os.path.exists(destination):
            with open(source, "rb") as source_file:
                source_bytes = source_file.read()
            with open(destination, "rb") as destination_file:
                destination_bytes = destination_file.read()
            if source_bytes != destination_bytes:
                raise RuntimeError(
                    f"staged binary legal file does not match repository copy: {destination}"
                )
            continue
        shutil.copy2(source, destination)
        staged.append(destination)

    return staged


class BuildPyWithNativeLib(build_py):
    def run(self):
        src = _find_native_lib()
        if src:
            dst = os.path.join(
                os.path.dirname(os.path.abspath(__file__)),
                "paimon_vindex",
                _lib_name(),
            )
            shutil.copy2(src, dst)
        staged_legal_files = _stage_legal_files(
            os.path.join(os.path.dirname(os.path.abspath(__file__)), "paimon_vindex")
        )
        try:
            super().run()
        finally:
            for path in staged_legal_files:
                os.remove(path)


class PlatformWheel(bdist_wheel):
    """Tag wheel as py3-none-{platform} since this is a ctypes package."""

    def finalize_options(self):
        bdist_wheel.finalize_options(self)
        self.root_is_pure = False

    def get_tag(self):
        _, _, plat = bdist_wheel.get_tag(self)
        return "py3", "none", plat


class BinaryDistribution(Distribution):
    """Force the wheel to be platform-specific."""

    def has_ext_modules(self):
        return True


staged_distribution_legal_files = _stage_legal_files(
    os.path.dirname(os.path.abspath(__file__))
)
try:
    setup(
        cmdclass={"build_py": BuildPyWithNativeLib, "bdist_wheel": PlatformWheel},
        distclass=BinaryDistribution,
    )
finally:
    for path in staged_distribution_legal_files:
        os.remove(path)
