import subprocess

import gdb
import objdump
import strip
from SCons.Action import _subproc
from SCons.Errors import StopError
from SCons.Tool import ar, asm, gcc, gnulink, gxx


def prefix_commands(env, command_prefix, cmd_list):
    for command in cmd_list:
        if command in env:
            prefixed_binary = command_prefix + env[command]
            if not env.WhereIs(prefixed_binary):
                raise StopError(
                    f"Toolchain binary {prefixed_binary} not found in PATH."
                )
            env.Replace(**{command: prefixed_binary})


def _get_tool_version(env, tool):
    verstr = "version unknown"
    proc = _subproc(
        env,
        [env.subst("${%s}" % tool), "--version"],
        stdout=subprocess.PIPE,
        stderr="devnull",
        stdin="devnull",
        universal_newlines=True,
        error="raise",
        shell=False,
    )
    if proc:
        verstr = proc.stdout.readline()
        proc.communicate()
    return verstr


def generate(env, **kw):
    if not env.get("VERBOSE", False):
        env.SetDefault(
            CCCOMSTR="\tCC\t${SOURCE}",
            CXXCOMSTR="\tCPP\t${SOURCE}",
            ASCOMSTR="\tASM\t${SOURCE}",
            ARCOMSTR="\tAR\t${TARGET}",
            RANLIBCOMSTR="\tRANLIB\t${TARGET}",
            LINKCOMSTR="\tLINK\t${TARGET}",
            INSTALLSTR="\tINSTALL\t${TARGET}",
            APPSCOMSTR="\tAPPS\t${TARGET}",
            VERSIONCOMSTR="\tVERSION\t${TARGET}",
            STRIPCOMSTR="\tSTRIP\t${TARGET}",
            OBJDUMPCOMSTR="\tOBJDUMP\t${TARGET}",
        )

    for orig_tool in (asm, gcc, gxx, ar, gnulink, strip, gdb, objdump):
        orig_tool.generate(env)
    env.SetDefault(
        TOOLCHAIN_PREFIX=kw.get("toolchain_prefix"),
    )
    prefix_commands(
        env,
        env.subst("$TOOLCHAIN_PREFIX"),
        [
            "AR",
            "AS",
            "CC",
            "CXX",
            "OBJCOPY",
            "RANLIB",
            "STRIP",
            "GDB",
            "GDBPY",
            "OBJDUMP",
        ],
    )
    # Call CC to check version
    if whitelisted_versions := kw.get("versions", ()):
        cc_version = _get_tool_version(env, "CC")
        # print("CC version =", cc_version)
        # print(list(filter(lambda v: v in cc_version, whitelisted_versions)))
        if not any(filter(lambda v: v in cc_version, whitelisted_versions)):
            raise StopError(
                f"Toolchain version is not supported. Allowed: {whitelisted_versions}, toolchain: {cc_version} "
            )


def exists(env):
    return True
