import os
from conan import ConanFile
from conan.tools.cmake import CMake, cmake_layout, CMakeDeps, CMakeToolchain
from conan.tools.files import copy
from conan.errors import ConanInvalidConfiguration


class LinkAheadConan(ConanFile):
    name = "linkahead"
    version = "0.3.0-dev"
    license = "AGPL-3.0-or-later"
    author = "Timm C. Fitschen <t.fitschen@indiscale.com>"
    url = "https://gitlab.indiscale.com/caosdb/src/caosdb-cpplib.git"
    description = "C++ library for the LinkAhead project"
    topics = ("data management", "linkahead", "caosdb")
    settings = "os", "compiler", "build_type", "arch"
    options = {
        "shared": [True, False],
        "fPIC": [True, False],
        "build_acm": [True, False],
    }
    default_options = {
        "shared": False,
        "fPIC": True,
        "build_acm": False,
    }

    exports = ("*.cmake", "*CMakeLists.txt", "*.in",
               "*.h", "*.proto", "*.c", "*.cpp",
               "*.rst", "*.md",
               )

    exports_sources = "CMakeLists.txt", "src/*", "doc/*", "include/*", "test/*", "cmake/*", "proto/*", "*.cmake"

    def build_requirements(self):
        self.tool_requires("protobuf/3.21.12")
        self.tool_requires("cmake/[>=3.13]")
        self.tool_requires("boost/1.80.0")
        self.test_requires("gtest/1.11.0")
        self.requires("grpc/1.48.4")
        self.requires("protobuf/3.21.12")
        self.requires("boost/1.80.0")

    def config_options(self):
        if self.settings.os == "Windows":
            self.options.rm_safe("fPIC")
        self.options["boost"].without_python = True
        self.options["boost"].without_test = True
        self.options["boost"].filesystem_version = "3"

    def generate(self):

        tc = CMakeToolchain(self)
        if self.options.build_acm:
            tc.cache_variables["BUILD_ACM"] = "ON"
        tc.generate()

        cmake = CMakeDeps(self)
        cmake.generate()

        for dep in self.dependencies.values():
            dst = self.build_folder + "/build_tools"
            src = dep.cpp_info.bindirs[0]
            copied = copy(self, pattern="protoc*", dst=dst, src=src)
            copy(self, pattern="grpc_cpp_plugin*", dst=dst, src=src)

    def layout(self):
        cmake_layout(self, src_folder=".")

    def build(self):
        cmake = CMake(self)

        cmake.configure()
        cmake.build()

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

        print(copy(self, pattern="*.h", 
             src=os.path.join(self.build_folder, "include"),
             dst=os.path.join(self.package_folder, "include")))
        print(copy(self, pattern="*.h",
             dst=os.path.join(self.package_folder, "include"),
             src=os.path.join(self.source_folder, "include")))
        copy(self, pattern="*.h",
             dst=os.path.join(self.package_folder, "include"),
             src=os.path.join(self.source_folder, "include"))
        copy(self, pattern="*.dll", src=os.path.join(self.build_folder, "bin"),
             dst=os.path.join(self.package_folder, "bin"), keep_path=False)
        copy(self, pattern="*.so", src=os.path.join(self.build_folder, "bin"),
             dst=os.path.join(self.package_folder, "lib"), keep_path=False)
        copy(self, pattern="*.dylib", src=os.path.join(self.build_folder, "bin"),
             dst=os.path.join(self.package_folder, "lib"), keep_path=False)
        copy(self, pattern="*.a", src=os.path.join(self.build_folder, "bin"),
             dst=os.path.join(self.package_folder, "lib"), keep_path=False)

    def package_info(self):
        self.cpp_info.libs = ["linkahead::linkahead", "linkahead::clinkahead", "linkahead::caosdb_grpc" ]
        self.cpp_info.requires = ["boost::headers", "grpc::grpc", "protobuf::protobuf"]
        self.cpp_info.bindirs = ["build/Release", "build/Debug"]
        self.cpp_info.includedirs = ["include", "build/include"]
        self.cpp_info.components["linkahead::linkahead"].libs = ["linkahead"]
        self.cpp_info.components["linkahead::linkahead"].set_property("cmake_target_name", "linkahead")

        self.cpp_info.components["linkahead::clinkahead"].libs = ["clinkahead"]
        self.cpp_info.components["linkahead::clinkahead"].set_property("cmake_target_name", "clinkahead")

        self.cpp_info.components["linkahead::caosdb_grpc"].libs = ["caosdb_grpc"]
        self.cpp_info.components["linkahead::caosdb_grpc"].set_property("cmake_target_name", "caosdb_grpc")
        

    def validate(self):
        if self.settings.os not in ("Linux", "Windows"):
            raise ConanInvalidConfiguration(f"{self.settings.os} is currently not supported")