from SCons.Builder import Builder
from SCons.Action import Action
from SCons.Script import Delete, Mkdir, GetBuildFailures, Flatten
import multiprocessing
import webbrowser
import atexit
import sys
import subprocess

__no_browser = False


def _set_browser_action(target, source, env):
    if env["PVSNOBROWSER"]:
        global __no_browser
        __no_browser = True


def emit_pvsreport(target, source, env):
    target_dir = env["REPORT_DIR"]
    if env["PLATFORM"] == "win32":
        # Report generator on Windows emits to a subfolder of given output folder
        target_dir = target_dir.Dir("fullhtml")
    return [target_dir.File("index.html")], source


def atexist_handler():
    global __no_browser
    if __no_browser:
        return

    for bf in GetBuildFailures():
        for node in Flatten(bf.node):
            if node.exists and node.name.endswith(".html"):
                # macOS
                if sys.platform == "darwin":
                    subprocess.run(["open", node.abspath])
                else:
                    webbrowser.open(node.abspath)
                break


def generate(env):
    env.SetDefault(
        PVSNCORES=multiprocessing.cpu_count(),
        PVSOPTIONS=[
            "@.pvsoptions",
            "-j${PVSNCORES}",
            # "--incremental", # kinda broken on PVS side
        ],
        PVSCONVOPTIONS=[
            "-a",
            "GA:1,2,3",
            "-t",
            "fullhtml",
            "--indicate-warnings",
        ],
    )

    if env["PLATFORM"] == "win32":
        env.SetDefault(
            PVSCHECKBIN="CompilerCommandsAnalyzer.exe",
            PVSCONVBIN="PlogConverter.exe",
        )
    else:
        env.SetDefault(
            PVSCHECKBIN="pvs-studio-analyzer",
            PVSCONVBIN="plog-converter",
        )

    if not env["VERBOSE"]:
        env.SetDefault(
            PVSCHECKCOMSTR="\tPVS\t${TARGET}",
            PVSCONVCOMSTR="\tPVSREP\t${TARGET}",
        )

    env.Append(
        BUILDERS={
            "PVSCheck": Builder(
                action=Action(
                    '${PVSCHECKBIN} analyze ${PVSOPTIONS} -f "${SOURCE}" -o "${TARGET}"',
                    "${PVSCHECKCOMSTR}",
                ),
                suffix=".log",
                src_suffix=".json",
            ),
            "PVSReport": Builder(
                action=Action(
                    [
                        Delete("${TARGET.dir}"),
                        # PlogConverter.exe and plog-converter have different behavior
                        Mkdir("${TARGET.dir}") if env["PLATFORM"] == "win32" else None,
                        Action(_set_browser_action, None),
                        '${PVSCONVBIN} ${PVSCONVOPTIONS} "${SOURCE}" -o "${REPORT_DIR}"',
                    ],
                    "${PVSCONVCOMSTR}",
                ),
                emitter=emit_pvsreport,
                src_suffix=".log",
            ),
        }
    )
    atexit.register(atexist_handler)


def exists(env):
    return True