import textwrap

import jinja2
from jinja2 import Template

from conan.internal.api.install.generators import relativize_path


class ConfigTemplate2:
    """
    FooConfig.cmake
    foo-config.cmake
    """
    def __init__(self, cmakedeps, conanfile):
        self._cmakedeps = cmakedeps
        self._conanfile = conanfile

    def content(self):
        t = Template(self._template, trim_blocks=True, lstrip_blocks=True,
                     undefined=jinja2.StrictUndefined)
        return t.render(self._context)

    @property
    def filename(self):
        f = self._cmakedeps.get_cmake_filename(self._conanfile)
        return f"{f}-config.cmake" if f == f.lower() else f"{f}Config.cmake"

    @property
    def _context(self):
        f = self._cmakedeps.get_cmake_filename(self._conanfile)
        targets_include = f"{f}Targets.cmake"
        pkg_name = self._conanfile.ref.name
        build_modules_paths = self._cmakedeps.get_property("cmake_build_modules", self._conanfile,
                                                           check_type=list) or []
        # FIXME: Proper escaping of paths for CMake and relativization
        # FIXME: build_module_paths coming from last config only
        build_modules_paths = [f.replace("\\", "/") for f in build_modules_paths]
        build_modules_paths = [relativize_path(p, self._cmakedeps._conanfile,
                                               "${CMAKE_CURRENT_LIST_DIR}")
                               for p in build_modules_paths]
        components = self._cmakedeps.get_property("cmake_components", self._conanfile,
                                                  check_type=list)
        if components is None:  # Lets compute the default components names
            components = []
            # This assumes that cmake_components is only defined with not multi .libs=[lib1, lib2]
            for name in self._conanfile.cpp_info.components:
                if name.startswith("_"):  # Skip private components
                    continue
                comp_components = self._cmakedeps.get_property("cmake_components", self._conanfile,
                                                               name, check_type=list)
                if comp_components:
                    components.extend(comp_components)
                else:
                    cmakename = self._cmakedeps.get_property("cmake_target_name", self._conanfile,
                                                             name)
                    if cmakename and "::" in cmakename:  # Remove package namespace
                        cmakename = cmakename.split("::", 1)[1]
                    components.append(cmakename or name)
        components = " ".join(components) if components else ""
        return {"filename": f,
                "components": components,
                "pkg_name": pkg_name,
                "targets_include_file": targets_include,
                "build_modules_paths": build_modules_paths}

    @property
    def _template(self):
        return textwrap.dedent("""\
        # Requires CMake > 3.15
        if(${CMAKE_VERSION} VERSION_LESS "3.15")
            message(FATAL_ERROR "The 'CMakeDeps' generator only works with CMake >= 3.15")
        endif()

        include(${CMAKE_CURRENT_LIST_DIR}/{{ targets_include_file }})

        get_property(isMultiConfig GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG)
        if(NOT isMultiConfig AND NOT CMAKE_BUILD_TYPE)
           message(FATAL_ERROR "Please, set the CMAKE_BUILD_TYPE variable when calling to CMake "
                               "adding the '-DCMAKE_BUILD_TYPE=<build_type>' argument.")
        endif()

        # build_modules_paths comes from last configuration only
        {% for build_module in build_modules_paths %}
        message(STATUS "Conan: Including build module from '{{build_module}}'")
        include("{{ build_module }}")
        {% endfor %}

        {% if components %}
        set({{filename}}_PACKAGE_PROVIDED_COMPONENTS {{components}})
        foreach(comp {%raw%}${{%endraw%}{{filename}}_FIND_COMPONENTS})
          if(NOT ${comp} IN_LIST {{filename}}_PACKAGE_PROVIDED_COMPONENTS)
            if({%raw%}${{%endraw%}{{filename}}_FIND_REQUIRED_${comp}})
              message(STATUS "Conan: Error: '{{pkg_name}}' required COMPONENT '${comp}' not found")
              set({{filename}}_FOUND FALSE)
            endif()
          endif()
        endforeach()
        {% endif %}
        """)
