from dhros.rosbuilder.rosbuilder import run
import itertools
import os
import re
import pytest
import dhros.common


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


@pytest.mark.parametrize("step", BUILD_STEPS)
def test_override_step(capsys, rosbuilder, step):
    run(rosbuilder, {f"ROS_EXECUTE_CUSTOM_{step.upper()}": "CUSTOMIZED COMMAND"})
    captured = capsys.readouterr()
    for test_step in BUILD_STEPS:
        if test_step == step:
            assert f"dh_auto_{test_step} " not in captured.out
        else:
            assert f"dh_auto_{test_step} " in captured.out
    assert "CUSTOMIZED COMMAND" in captured.out


@pytest.mark.parametrize("step,btype", itertools.product(BUILD_STEPS, BUILD_TYPES))
def test_override_type_step(capsys, rosbuilder, step, btype):
    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):
        if test_step == step and test_type == btype:
            assert f"dh_auto_{test_step} --sourcedir=foo_{test_type} " not in captured.out
        else:
            assert f"dh_auto_{test_step} --sourcedir=foo_{test_type} " in captured.out
    assert "CUSTOMIZED COMMAND" in captured.out


@pytest.mark.parametrize("step", BUILD_STEPS)
def test_before_hook(capsys, rosbuilder, step):
    run(rosbuilder, {f"ROS_EXECUTE_BEFORE_{step.upper()}": "CUSTOMIZED COMMAND"})
    captured = capsys.readouterr()
    for test_step in BUILD_STEPS:
        if test_step == step:
            assert f"CUSTOMIZED COMMAND\ndh_auto_{test_step} " in captured.out
        else:
            assert f"CUSTOMIZED COMMAND\ndh_auto_{test_step} " not in captured.out


@pytest.mark.parametrize("step", BUILD_STEPS)
def test_after_hook(capsys, rosbuilder, step):
    run(rosbuilder, {f"ROS_EXECUTE_AFTER_{step.upper()}": "CUSTOMIZED COMMAND"})
    captured = capsys.readouterr()
    for test_step in BUILD_STEPS:
        if test_step == step:
            assert re.search(f"dh_auto_{test_step} .*\nCUSTOMIZED COMMAND", captured.out)
        else:
            assert not re.search(f"dh_auto_{test_step} .*\nCUSTOMIZED COMMAND", captured.out)


@pytest.mark.parametrize("step,btype", itertools.product(BUILD_STEPS, BUILD_TYPES))
def test_before_type_hook(capsys, rosbuilder, step, btype):
    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):
        if test_step == step and test_type == btype:
            assert f"CUSTOMIZED COMMAND\ndh_auto_{test_step} --sourcedir=foo_{test_type} " in captured.out
        else:
            assert f"CUSTOMIZED COMMAND\ndh_auto_{test_step} --sourcedir=foo_{test_type} " not in captured.out


@pytest.mark.parametrize("step,btype", itertools.product(BUILD_STEPS, BUILD_TYPES))
def test_after_type_hook(capsys, rosbuilder, step, btype):
    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):
        if test_step == step and test_type == btype:
            assert re.search(f"dh_auto_{test_step} --sourcedir=foo_{test_type} .*\nCUSTOMIZED COMMAND", captured.out)
        else:
            assert not re.search(f"dh_auto_{test_step} --sourcedir=foo_{test_type} .*\nCUSTOMIZED COMMAND", captured.out)


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


@pytest.mark.parametrize("step,btype", itertools.product(BUILD_STEPS, BUILD_TYPES))
def test_extra_type_args(capsys, rosbuilder, step, btype):
    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):
        if test_step == step and test_type == btype:
            assert re.search(f"(?m)dh_auto_{test_step} --sourcedir=foo_{test_type} .* EXTRA ARGS$", captured.out)
        else:
            assert not re.search(f"(?m)dh_auto_{test_step} --sourcedir=foo_{test_type} .* EXTRA ARGS$", captured.out)


@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]:
        if test_package == package:
            assert f"dh_auto_build --sourcedir={test_package} " not in captured.out
        else:
            assert f"dh_auto_build --sourcedir={test_package} " in captured.out

