from pathlib import Path
from conan import ConanFile
from conan.tools.cmake import CMakeToolchain, CMake, cmake_layout, CMakeDeps
from conan.tools.files import copy, rmdir, chdir, move_folder_contents
from conan.tools.scm import Git
from conan.tools.files import patch


class ConanOpenVapiDevFull(ConanFile):
    name = "open-vehicle-api-dev-full"
    license = "Apache-2.0"
    author = "thommyho <thommyho1988@gmail.com>"
    url = "https://github.com/eclipse-openvehicle-api/openvehicle-api"
    homepage = "https://eclipse.dev/openvehicle-api/"
    description = (
        "The Eclipse Open Vehicle API (VAPI) provides tools and a runtime "
        "to create a vehicle abstraction interface for signal- and event-driven functions."
    )
    topics = (
        "automotive",
        "sdv",
        "software-defined-vehicle",
        "vehicle-abstraction",
        "vss",
        "vehicle-signal-specification",
        "middleware",
        "embedded",
        "c++",
    )

    settings = "os", "arch", "compiler", "build_type"
    exports_sources = "LICENSE", "patches/**"

    options = {"build_with_tests": [True, False]}
    default_options = {"build_with_tests": False}

    def build_requirements(self):
        self.tool_requires("cmake/3.31.10")
        self.tool_requires("make/4.4.1")

    def layout(self):
        cmake_layout(self)

    def source(self):
        # rmdir(self, self.source_folder)
        if self.version in self.conan_data.get("sources", {}):
            data = self.conan_data["sources"][self.version]
            git = Git(self)
            git_folder = Path(self.source_folder) / "src"
            git.clone(url=data["url"], target=str(git_folder))
            with chdir(self, str(git_folder)):
                git.checkout(data["revision"])
            # Move contents from 'src' to root if needed
            move_folder_contents(
                self, src_folder=str(git_folder), dst_folder=self.source_folder
            )
        else:
            self.output.warning(
                f"No source defined for version {self.version} in conandata.yml"
            )

    def generate(self):
        deps = CMakeDeps(self)
        deps.generate()

        tc = CMakeToolchain(self)

        # Path construction
        # Note: We use .as_posix() because CMake prefers forward slashes even on Windows
        bin_build_path = Path(self.build_folder) / "bin"
        include_source_path = Path(self.source_folder) / "export"

        tc.cache_variables["SDV_FRAMEWORK_RUNTIME"] = bin_build_path.as_posix()
        tc.cache_variables["SDV_COMPONENT_INSTALL"] = bin_build_path.as_posix()
        tc.cache_variables["SDV_FRAMEWORK_DEV_TOOLS"] = bin_build_path.as_posix()
        tc.cache_variables["SDV_FRAMEWORK_DEV_INCLUDE"] = include_source_path.as_posix()
        # For faster build skip test
        if not self.options.build_with_tests:
            tc.cache_variables["SDV_FRAMEWORK_BUILD_SKIP_TESTS"] = True
        else:
            tc.cache_variables["SDV_FRAMEWORK_BUILD_SKIP_TESTS"] = False

        tc.generate()

    def build(self):
        ## Warning -- Ugly working around exporting issue
        patch_file = (
            Path(self.recipe_folder)
            / ".."
            / "es"
            / "patches"
            / "dev-only-skip-tests.patch"
        )
        self.output.info(f"Patching with {patch_file}")
        patch_dir = Path(self.source_folder)
        self.output.info(f"Patching in directory {patch_dir}")
        patch(self, patch_file=patch_file, base_path=patch_dir)

        cmake = CMake(self)
        cmake.configure()
        cmake.build()

    def package(self):
        cmake = CMake(self)
        cmake.install()

        # Clean up using Path
        pkg_path = Path(self.package_folder)

        # Convert to str because rmdir expects a string path, not a Path object
        rmdir(self, str(pkg_path / "include"))
        rmdir(self, str(pkg_path / "lib"))

        # Copy artifacts
        # Conan's copy() helper handles patterns, so we pass strings for patterns
        # but we can use Path for src/dst
        copy(self, "bin*", src=self.build_folder, dst=self.package_folder)
        copy(self, "export*", src=self.source_folder, dst=self.package_folder)
        copy(
            self,
            "LICENSE*",
            src=Path(self.recipe_folder) / ".." / "es",
            dst=Path(self.package_folder),
        )

    def package_info(self):
        self.cpp_info.bindirs = ["bin"]
        self.cpp_info.includedirs = ["export"]

        # Define map relative to package folder
        sdv_env_map = {
            "SDV_FRAMEWORK_RUNTIME": "bin",
            "SDV_COMPONENT_INSTALL": "bin",
            "SDV_FRAMEWORK_DEV_TOOLS": "bin",
            "SDV_FRAMEWORK_DEV_INCLUDE": "export",
        }

        pkg_path = Path(self.package_folder)

        for var, rel_path in sdv_env_map.items():
            # Construct absolute path
            abs_path_obj = pkg_path / rel_path

            # IMPORTANT: Convert to string/posix for environment variable definitions
            abs_path_str = abs_path_obj.as_posix()

            self.runenv_info.define_path(var, abs_path_str)
            self.buildenv_info.define_path(var, abs_path_str)
