#!/usr/bin/python3
# coding: utf-8
# Copyright (c) 2024 Huawei Technologies Co., Ltd.
# openUBMC is licensed under Mulan PSL v2.
# You can use this software according to the terms and conditions of the Mulan PSL v2.
# You may obtain a copy of Mulan PSL v2 at:
#         http://license.coscl.org.cn/MulanPSL2
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
# See the Mulan PSL v2 for more details.
import os
import shutil
import logging
import platform
import subprocess
import tempfile
import argparse

from bmcgo import __version__
from bmcgo import misc

cwd = os.getcwd()
BINGO_SRC_DIR = "bmcgo"


def get_deb_arch():
    arch = platform.machine()
    if arch == "x86_64":
        arch = "amd64"

    dpkg = shutil.which("dpkg")
    if dpkg is None or not os.path.exists(dpkg):
        return arch
    
    try:
        ret = subprocess.run(
            [dpkg, "--print-architecture"], 
            check=True, capture_output=True, text=True
        )
        return ret.stdout.strip()
    except Exception as e:
        return arch


class Build(object):
    def __init__(self, args):
        self.output_dir = os.path.join(cwd, "output")
        self.package_name = args.package_name
        if os.path.isdir(self.output_dir):
            shutil.rmtree(self.output_dir)
        self.pip_out = os.path.join(self.output_dir, "PyPI/openubmc/openubmc-bingo", __version__)
        self.deb_out = os.path.join(self.output_dir, "Generic/openubmc/openubmc-bingo", __version__)
        os.makedirs(self.pip_out)
        os.makedirs(self.deb_out)

    def run_command(self, command, check=True):
        """
        如果ignore_error为False，命令返回码非0时则打印堆栈和日志并触发异常，中断构建
        """
        logging.info("执行命令: (%s)", " ".join(command))
        subprocess.run(command, check=check)

    def package_pip(self):
        """
        构建bmcgo工具的pip包
        """
        setup_file = "setup.py"
        req_file = "requirements.txt"
        tmp_dir = tempfile.TemporaryDirectory()
        build_dir = os.path.join(tmp_dir.name, BINGO_SRC_DIR)
        shutil.copytree(BINGO_SRC_DIR, build_dir)
        shutil.copyfile(req_file, os.path.join(tmp_dir.name, req_file))
        shutil.copyfile(setup_file, os.path.join(tmp_dir.name, setup_file))
        shutil.copyfile("MANIFEST.in", os.path.join(tmp_dir.name, "MANIFEST.in"))
        if os.path.isdir("dist"):
            shutil.rmtree("dist")
        os.chdir(tmp_dir.name)
        cmd = ["/usr/bin/python3", setup_file, "bdist_wheel"]
        self.run_command(cmd)
        file_name = self.package_name.replace("-", "_")
        cmd = ["/usr/bin/cp", f"dist/{file_name}-{__version__}-py3-none-any.whl", self.pip_out]
        self.run_command(cmd)
        case_folder = os.path.join(tmp_dir.name, BINGO_SRC_DIR, "error_cases")
        os.chdir(case_folder)
        self.package_bingo_cases()
        os.chdir(cwd)

    def package_bingo_cases(self):
        cmd = ["conan", "create", "."]
        self.run_command(cmd)

    def build_tools(self, deb_dir):
        temp_dir = tempfile.TemporaryDirectory()
        build_dir = os.path.join(temp_dir.name, "build_tools")
        shutil.copytree(os.path.join("tools", "src"), build_dir)
        os.chdir(build_dir)
        if misc.conan_v1():
            run_cmd = ["conan", "create", ".", "bingo_tools/0.0.1@release/rc", "-pr", "default", "--build"]
            self.run_command(run_cmd)
            run_cmd = [
                "conan", "install", "bingo_tools/0.0.1@release/rc", "-pr", "default",
                "-if", ".temp", "-g", "deploy"
            ]
            self.run_command(run_cmd)
            shutil.copytree(".temp/bingo_tools", deb_dir, dirs_exist_ok=True)
        else:
            self.run_command(["mv", "conanfile_v2.py", "conanfile.py"])
            run_cmd = ["conan", "create", ".", "-c", "tools.system.package_manager:mode=install"]
            self.run_command(run_cmd)
            run_cmd = [
                "conan", "install", "--requires=bingo_tools/0.0.2", "--deployer-folder=.temp",
                "-of", ".temp", "-d", "direct_deploy", "-c", "tools.system.package_manager:mode=install"
            ]
            self.run_command(run_cmd)
            self.run_command(["rm", ".temp/direct_deploy/bingo_tools/conanmanifest.txt"])
            self.run_command(["rm", ".temp/direct_deploy/bingo_tools/conaninfo.txt"])
            shutil.copytree(".temp/direct_deploy/bingo_tools", deb_dir, dirs_exist_ok=True)
        os.chdir(cwd)

    def package_deb(self):
        """
        打包deb包
        """
        logging.info("开始打 deb 包")
        tmp_dir = tempfile.TemporaryDirectory()
        deb_dir = os.path.join(tmp_dir.name, "deb")
        shutil.copytree(os.path.join(cwd, "tools", "deb"), deb_dir)

        control = os.path.join(deb_dir, "DEBIAN/control")
        cmd = ["/usr/bin/sed", "-i", f"s@<version>@{__version__}@g", control]
        self.run_command(cmd)

        self.build_tools(deb_dir)

        mach = get_deb_arch()
        dst = os.path.join(self.deb_out, f"openubmc_bingo_{mach}.deb")
        self.run_command(["/usr/bin/dpkg", "-b", deb_dir, dst])


if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="build package", formatter_class=argparse.RawTextHelpFormatter)
    parser.add_argument("--package_name", help="package name", default='openubmc-bingo')
    args = parser.parse_args()
    b = Build(args)
    b.package_pip()
    b.package_deb()
