# Copyright 2021-2022 Timo Röhling <roehling@debian.org>
# SPDX-License-Identifier: MIT
from dhros.rosbuilder.rosbuilder import run, cmdind
import itertools
import os
import re
import pytest
import dhros.common


BUILD_STEPS = ["configure", "build", "test", "install", "clean"]
BUILD_TYPES = ["ament_cmake", "ament_python", "catkin", "cmake"]


@pytest.mark.parametrize("step", BUILD_STEPS)
def test_override_step(capsys, rosbuilder, step):
    run(
        rosbuilder("--clean"),
        {f"ROS_EXECUTE_CUSTOM_{step.upper()}": "CUSTOMIZED COMMAND"},
    )
    run(rosbuilder(), {f"ROS_EXECUTE_CUSTOM_{step.upper()}": "CUSTOMIZED COMMAND"})
    captured = capsys.readouterr()
    for test_step in BUILD_STEPS:
        assert bool(re.search(f"(?m)^{cmdind}dh_auto_{test_step} ", captured.out)) == (
            test_step != step
        )
    assert re.search(f"(?m)^{cmdind}CUSTOMIZED COMMAND$", captured.out)


@pytest.mark.parametrize("step,btype", itertools.product(BUILD_STEPS, BUILD_TYPES))
def test_override_type_step(capsys, rosbuilder, step, btype):
    run(
        rosbuilder("--clean"),
        {f"ROS_EXECUTE_CUSTOM_{step.upper()}_{btype.upper()}": "CUSTOMIZED COMMAND"},
    )
    run(
        rosbuilder(),
        {f"ROS_EXECUTE_CUSTOM_{step.upper()}_{btype.upper()}": "CUSTOMIZED COMMAND"},
    )
    captured = capsys.readouterr()
    for test_step, test_type in itertools.product(BUILD_STEPS, BUILD_TYPES):
        assert bool(
            re.search(
                f"(?m)^{cmdind}dh_auto_{test_step} --sourcedir=foo_{test_type} ",
                captured.out,
            )
        ) == (test_step != step or test_type != btype)
    assert re.search(f"(?m)^{cmdind}CUSTOMIZED COMMAND$", captured.out)


@pytest.mark.parametrize("step", BUILD_STEPS)
def test_before_hook(capsys, rosbuilder, step):
    run(
        rosbuilder("--clean"),
        {f"ROS_EXECUTE_BEFORE_{step.upper()}": "CUSTOMIZED COMMAND"},
    )
    run(rosbuilder(), {f"ROS_EXECUTE_BEFORE_{step.upper()}": "CUSTOMIZED COMMAND"})
    captured = capsys.readouterr()
    for test_step in BUILD_STEPS:
        assert bool(
            re.search(
                f"(?m)^{cmdind}CUSTOMIZED COMMAND\n{cmdind}dh_auto_{test_step} ",
                captured.out,
            )
        ) == (test_step == step)


@pytest.mark.parametrize("step", BUILD_STEPS)
def test_after_hook(capsys, rosbuilder, step):
    run(
        rosbuilder("--clean"),
        {f"ROS_EXECUTE_AFTER_{step.upper()}": "CUSTOMIZED COMMAND"},
    )
    run(rosbuilder(), {f"ROS_EXECUTE_AFTER_{step.upper()}": "CUSTOMIZED COMMAND"})
    captured = capsys.readouterr()
    for test_step in BUILD_STEPS:
        assert bool(
            re.search(
                f"(?m)^{cmdind}dh_auto_{test_step} .*\n{cmdind}CUSTOMIZED COMMAND$",
                captured.out,
            )
        ) == (test_step == step)


@pytest.mark.parametrize("step,btype", itertools.product(BUILD_STEPS, BUILD_TYPES))
def test_before_type_hook(capsys, rosbuilder, step, btype):
    run(
        rosbuilder("--clean"),
        {f"ROS_EXECUTE_BEFORE_{step.upper()}_{btype.upper()}": "CUSTOMIZED COMMAND"},
    )
    run(
        rosbuilder(),
        {f"ROS_EXECUTE_BEFORE_{step.upper()}_{btype.upper()}": "CUSTOMIZED COMMAND"},
    )
    captured = capsys.readouterr()
    for test_step, test_type in itertools.product(BUILD_STEPS, BUILD_TYPES):
        assert bool(
            re.search(
                f"(?m)^{cmdind}CUSTOMIZED COMMAND\n{cmdind}dh_auto_{test_step} --sourcedir=foo_{test_type} ",
                captured.out,
            )
        ) == (test_step == step and test_type == btype)


@pytest.mark.parametrize("step,btype", itertools.product(BUILD_STEPS, BUILD_TYPES))
def test_after_type_hook(capsys, rosbuilder, step, btype):
    run(
        rosbuilder("--clean"),
        {f"ROS_EXECUTE_AFTER_{step.upper()}_{btype.upper()}": "CUSTOMIZED COMMAND"},
    )
    run(
        rosbuilder(),
        {f"ROS_EXECUTE_AFTER_{step.upper()}_{btype.upper()}": "CUSTOMIZED COMMAND"},
    )
    captured = capsys.readouterr()
    for test_step, test_type in itertools.product(BUILD_STEPS, BUILD_TYPES):
        assert bool(
            re.search(
                f"(?m)^{cmdind}dh_auto_{test_step} --sourcedir=foo_{test_type} .*\n{cmdind}CUSTOMIZED COMMAND$",
                captured.out,
            )
        ) == (test_step == step and test_type == btype)


@pytest.mark.parametrize("step", BUILD_STEPS)
def test_extra_args(capsys, rosbuilder, step):
    run(rosbuilder("--clean"), {f"ROS_{step.upper()}_ARGS": "EXTRA ARGS"})
    run(rosbuilder(), {f"ROS_{step.upper()}_ARGS": "EXTRA ARGS"})
    captured = capsys.readouterr()
    for test_step in BUILD_STEPS:
        assert bool(
            re.search(f"(?m)^{cmdind}dh_auto_{test_step} .* EXTRA ARGS$", captured.out)
        ) == (test_step == step)


@pytest.mark.parametrize("step,btype", itertools.product(BUILD_STEPS, BUILD_TYPES))
def test_extra_type_args(capsys, rosbuilder, step, btype):
    run(
        rosbuilder("--clean"),
        {f"ROS_{step.upper()}_{btype.upper()}_ARGS": "EXTRA ARGS"},
    )
    run(rosbuilder(), {f"ROS_{step.upper()}_{btype.upper()}_ARGS": "EXTRA ARGS"})
    captured = capsys.readouterr()
    for test_step, test_type in itertools.product(BUILD_STEPS, BUILD_TYPES):
        assert bool(
            re.search(
                f"(?m)^{cmdind}dh_auto_{test_step} --sourcedir=foo_{test_type} .* EXTRA ARGS$",
                captured.out,
            )
        ) == (test_step == step and test_type == btype)


@pytest.mark.parametrize("step", BUILD_STEPS)
def test_command_prefix(capsys, rosbuilder, step):
    run(rosbuilder("--clean"), {f"ROS_{step.upper()}_WRAPPER": "WRAPPING COMMAND"})
    run(rosbuilder(), {f"ROS_{step.upper()}_WRAPPER": "WRAPPING COMMAND"})
    captured = capsys.readouterr()
    for test_step in BUILD_STEPS:
        assert bool(
            re.search(
                f"(?m)^{cmdind}WRAPPING COMMAND dh_auto_{test_step}", captured.out
            )
        ) == (test_step == step)


@pytest.mark.parametrize("step,btype", itertools.product(BUILD_STEPS, BUILD_TYPES))
def test_type_command_prefix(capsys, rosbuilder, step, btype):
    run(
        rosbuilder("--clean"),
        {f"ROS_{step.upper()}_{btype.upper()}_WRAPPER": "WRAPPING COMMAND"},
    )
    run(
        rosbuilder(),
        {f"ROS_{step.upper()}_{btype.upper()}_WRAPPER": "WRAPPING COMMAND"},
    )
    captured = capsys.readouterr()
    for test_step, test_type in itertools.product(BUILD_STEPS, BUILD_TYPES):
        assert bool(
            re.search(
                f"(?m)^{cmdind}WRAPPING COMMAND dh_auto_{test_step} --sourcedir=foo_{test_type} ",
                captured.out,
            )
        ) == (test_step == step and test_type == btype)


@pytest.mark.parametrize("package", [f"foo_{t}" for t in BUILD_TYPES])
def test_skip_package(capsys, rosbuilder, package):
    run(rosbuilder(), {f"ROS_SKIP_PACKAGES": package})
    captured = capsys.readouterr()
    for test_package in [f"foo_{t}" for t in BUILD_TYPES]:
        assert bool(
            re.search(
                f"(?m)^{cmdind}dh_auto_build --sourcedir={test_package} ", captured.out
            )
        ) == (test_package != package)


@pytest.mark.parametrize("package", [f"foo_{t}" for t in BUILD_TYPES] + ["1"])
def test_skip_tests(capsys, rosbuilder, package):
    run(rosbuilder(), {f"ROS_SKIP_TESTS": package})
    captured = capsys.readouterr()
    for test_package in [f"foo_{t}" for t in BUILD_TYPES]:
        assert re.search(
            f"(?m)^{cmdind}dh_auto_build --sourcedir={test_package} ", captured.out
        )
        assert bool(
            re.search(
                f"(?m)^{cmdind}dh_auto_test --sourcedir={test_package} ", captured.out
            )
        ) == (test_package != package and package != "1")
        if test_package != "foo_ament_python":
            build_testing = (
                "ON" if test_package != package and package != "1" else "OFF"
            )
            assert re.search(
                f"(?m)^{cmdind}dh_auto_configure --sourcedir={test_package} .* -DBUILD_TESTING={build_testing}",
                captured.out,
            )
