# monkey patch before anything else
from dev_tools.build.freeze.cx.patch import patch_cx_freeze

patch_cx_freeze()

import platform
import sys

import setuptools
from cx_Freeze import setup, Executable

from dev_tools.build.freeze.cx.build_exe import build_exe_nano
from dev_tools.build.freeze.cx.options import NanoBuildOptions
from dev_tools.utility.git import get_build_version_by_git


def setup_nano(**kwargs):
    if any(k in kwargs for k in ("executables", "options")):
        raise Exception("forbidden in setup kwargs")
    if int(setuptools.__version__.partition(".")[0]) >= 61:
        # FIXME: solve this, maybe only happens on darwin (does not happen on win)
        raise Exception("setuptools 61+ calls build_py for some reason, breaking cx_freeze build")

    NanoBuildOptions.TAG_VERSION, NanoBuildOptions.GIT_VERSION = get_build_version_by_git()

    # custom commands
    command_classes = kwargs.setdefault("cmdclass", {})
    command_classes["build_exe"] = build_exe_nano
    if sys.platform == "darwin":
        from dev_tools.build.freeze.cx.bdist_mac import bdist_dmg_nano, bdist_mac_nano

        command_classes["bdist_dmg"] = bdist_dmg_nano
        command_classes["bdist_mac"] = bdist_mac_nano

    # create executables
    if NanoBuildOptions.DEVELOPMENT_BUILD:
        from clarabot_nano.development.__main__ import DevelopmentClarabotNanoLauncher as Launcher
    else:
        from clarabot_nano.__main__ import ClarabotNanoLauncher as Launcher

    def _define_executable(target_name, base=None):
        return Executable(
            f"{Launcher.__module__.replace('.', '/')}.py",
            base=base,
            target_name=target_name,
            init_script=str(NanoBuildOptions.ROOT / "dev_tools/build/freeze/cx/init.py"),
            icon=str(NanoBuildOptions.ROOT / "clarabot_nano/resource/image/clarabot_nano.ico"),
            copyright="Clarabot Zrt",
            # trademarks="Clarabot Nano",  # ?
        )

    executables = [_define_executable("Clarabot Nano" if sys.platform.startswith("darwin") else "clarabot-nano")]
    if sys.platform.startswith("win"):
        executables.append(_define_executable("clarabot-nanow", "Win32GUI"))
    kwargs["executables"] = executables
    includes = ["concurrent_log_handler"]
    includes.extend(f"{mod}.__main__" for mod in Launcher.get_launch_targets())

    # command options
    kwargs["options"] = {
        "build_exe": {
            "optimize": 1,  # pycparser does not support -OO
            # "replace_paths": [("*", ".")],
            "includes": includes,
            "zip_include_packages": [],
            "zip_exclude_packages": ["*"],
            # windows
            "include_msvcr": True,
        },
        "bdist_mac": {
            "iconfile": str(NanoBuildOptions.ROOT / "clarabot_nano/resource/image/clarabot_nano.icns"),
            "bundle_name": f"Clarabot Nano{' Dev' if NanoBuildOptions.DEVELOPMENT_BUILD else ''}",
            # TODO: use custom codesign
            # "codesign_identity": None if NanoBuildOptions.SKIP_SIGNING else SIGNING_IDENTITY_NAME,
        },
        "bdist_dmg": {
            "volume_label": f"clarabot-nano{'-dev' if NanoBuildOptions.DEVELOPMENT_BUILD else ''}"
            f"-{NanoBuildOptions.TAG_VERSION}{NanoBuildOptions.GIT_VERSION}"
            f"{'-aarch64' if platform.machine() == 'arm64' else '-intel64'}",
            "applications_shortcut": True,  # to help installing it
        },
    }

    # select command and execute
    if NanoBuildOptions.SETUP_COMMAND is not None:
        command = NanoBuildOptions.SETUP_COMMAND
    elif sys.platform.startswith("darwin"):
        command = "bdist_dmg"
    else:
        command = "build_exe"
    _argv = sys.argv[:]
    sys.argv[:] = _argv[:1] + [command]
    try:
        setup(**kwargs)
    finally:
        sys.argv[:] = _argv
