# -*- coding: utf-8 -*-

from . import create_configuration, create_remote_conan_templates, conan
from bincrafters_templates import PROJECT_TYPES
from bincrafters_templates.bincrafters_templates import BincraftersTemplatesError, Configuration, generate_project, \
    template_geturl, template_seturl, template_update
import git
from pathlib import Path
import pytest
from pytest_cases import pytest_fixture_plus


@pytest_fixture_plus
@pytest.mark.parametrize("template_type", PROJECT_TYPES, ids=lambda t: f"template_type:{t}")
def valid_template_type(template_type):
    return template_type


def _test_valid_template_type(configuration, template_type, outputpath, conan):
    name = "conan-testname"

    generate_project(configuration, template_type=template_type, output=outputpath, name=name)

    project_path = outputpath / name

    assert (project_path / "test_package").is_dir()
    assert (project_path / ".ci").is_dir()
    assert (project_path / ".github").is_dir()
    assert (project_path / ".gitattributes").is_file()
    assert (project_path / ".gitignore").is_file()
    assert (project_path / ".travis.yml").is_file()
    assert (project_path / "appveyor.yml").is_file()

    assert project_path.is_dir()
    conanfile_path = project_path / "conanfile.py"
    assert conanfile_path.is_file()

    conan.inspect(str(conanfile_path), ("name", "version", ))
    return conanfile_path


def test_valid_template_type(valid_template_type, tmpdir_factory, conan):
    """ Generate valid project """
    output_path = Path(tmpdir_factory.mktemp("output"))
    configuration = create_configuration(tmpdir_factory)

    _test_valid_template_type(configuration, valid_template_type, output_path, conan)


def test_invalid_template_type(tmpdir_factory):
    """ Cannot generate project because invalid template type """
    output_path = Path(tmpdir_factory.mktemp("output"))
    configuration = create_configuration(tmpdir_factory)

    name = "conan-testname"
    invalid_template_type = "nonsense"
    try:
        generate_project(configuration, invalid_template_type, output_path, name)
        assert False, "An error should have been thrown"
    except BincraftersTemplatesError:
        pass


def test_default_template(tmpdir_factory, conan):
    output_path = Path(tmpdir_factory.mktemp("output"))
    configuration = create_configuration(tmpdir_factory)

    c = _test_valid_template_type(configuration, "default", output_path, conan)

    answer = conan.inspect(str(c), ("settings", "options", ))

    assert answer["settings"] is not None
    assert answer["options"] is not None

    assert "os" in answer["settings"]
    assert "arch" in answer["settings"]

    assert "os_build" not in answer["settings"]
    assert "arch_build" not in answer["settings"]

    assert "compiler" in answer["settings"]
    assert "build_type" in answer["settings"]
    assert "shared" in answer["options"]
    assert "fPIC" in answer["options"]


def test_header_only_template(tmpdir_factory, conan):
    output_path = Path(tmpdir_factory.mktemp("output"))
    configuration = create_configuration(tmpdir_factory)

    c = _test_valid_template_type(configuration, "header_only", output_path, conan)

    answer = conan.inspect(str(c), ("settings", "options", ))

    assert answer["settings"] is None
    assert answer["options"] is None


def test_install_only_template(tmpdir_factory, conan):
    output_path = Path(tmpdir_factory.mktemp("output"))
    configuration = create_configuration(tmpdir_factory)

    c = _test_valid_template_type(configuration, "installer_only", output_path, conan)

    answer = conan.inspect(str(c), ("settings", "options", ))

    assert answer["settings"] is not None
    assert answer["options"] is None

    assert "os" not in answer["settings"]
    assert "arch" not in answer["settings"]

    assert "os_build" in answer["settings"]
    assert "arch_build" in answer["settings"]

    assert "build_type" not in answer["settings"]


def test_change_remote(tmpdir_factory, conan):
    output_path = Path(tmpdir_factory.mktemp("output"))

    c0 = create_configuration(tmpdir_factory)
    c1 = create_configuration(tmpdir_factory)

    u0 = Path(next(template_geturl(c0)))
    u1 = Path(next(template_geturl(c1)))

    r0 = git.Repo(u0)
    (u0 / "dummy_c0").touch()
    r0.index.add(["dummy_c0"])
    r0.index.commit("added dummy_c0")

    r1 = git.Repo(u1)
    (u1 / "dummy_c1").touch()
    r1.index.add(["dummy_c1"])
    r1.index.commit("added dummy_c1")

    template_seturl(c0, u1)
    template_update(c0)

    assert (c0.template_path / "dummy_c1").is_file()


def test_updated_remote(tmpdir_factory, conan):
    output_path = Path(tmpdir_factory.mktemp("output"))
    configuration = create_configuration(tmpdir_factory)

    c = _test_valid_template_type(configuration, "default", output_path, conan)

    remote_path = Path(next(template_geturl(configuration)))
    assert Path(tmpdir_factory.getbasetemp()) in remote_path.parents

    r = git.Repo(remote_path)
    (remote_path / "dummy_file").touch()
    r.index.add(["dummy_file"])
    r.index.commit("added dummy_file")

    template_update(configuration)
    assert (configuration.template_path / "dummy_file").is_file()
