import glob
import os
import re
from conans import ConanFile, AutoToolsBuildEnvironment, CMake, tools
from conans.errors import ConanInvalidConfiguration

required_conan_version = ">=1.43.0"


class LibcurlConan(ConanFile):
    name = "libcurl"

    description = "command line tool and library for transferring data with URLs"
    topics = ("curl", "libcurl", "data-transfer")
    url = "https://github.com/conan-io/conan-center-index"
    homepage = "https://curl.haxx.se"
    license = "MIT"

    settings = "os", "arch", "compiler", "build_type"
    options = {
        "shared": [True, False],
        "fPIC": [True, False],
        "with_ssl": [False, "openssl", "wolfssl", "schannel", "darwinssl", "mbedtls"],
        "with_file": [True, False],
        "with_ftp": [True, False],
        "with_http": [True, False],
        "with_ldap": [True, False],
        "with_rtsp": [True, False],
        "with_dict": [True, False],
        "with_telnet": [True, False],
        "with_tftp": [True, False],
        "with_pop3": [True, False],
        "with_imap": [True, False],
        "with_smb": [True, False],
        "with_smtp": [True, False],
        "with_gopher": [True, False],
        "with_mqtt": [True, False],
        "with_libssh2": [True, False],
        "with_libidn": [True, False],
        "with_librtmp": [True, False],
        "with_libmetalink": [True, False],
        "with_libpsl": [True, False],
        "with_largemaxwritesize": [True, False],
        "with_nghttp2": [True, False],
        "with_zlib": [True, False],
        "with_brotli": [True, False],
        "with_zstd": [True, False],
        "with_c_ares": [True, False],
        "with_proxy": [True, False],
        "with_crypto_auth": [True, False],
        "with_ntlm": [True, False],
        "with_ntlm_wb": [True, False],
        "with_cookies": [True, False],
        "with_ipv6": [True, False],
        "with_docs": [True, False],
        "with_verbose_debug": [True, False],
        "with_symbol_hiding": [True, False],
        "with_unix_sockets": [True, False],
    }
    default_options = {
        "shared": False,
        "fPIC": True,
        "with_ssl": "openssl",
        "with_dict": True,
        "with_file": True,
        "with_ftp": True,
        "with_gopher": True,
        "with_http": True,
        "with_imap": True,
        "with_ldap": False,
        "with_mqtt": True,
        "with_pop3": True,
        "with_rtsp": True,
        "with_smb": True,
        "with_smtp": True,
        "with_telnet": True,
        "with_tftp": True,
        "with_libssh2": False,
        "with_libidn": False,
        "with_librtmp": False,
        "with_libmetalink": False,
        "with_libpsl": False,
        "with_largemaxwritesize": False,
        "with_nghttp2": False,
        "with_zlib": True,
        "with_brotli": False,
        "with_zstd": False,
        "with_c_ares": False,
        "with_proxy": True,
        "with_crypto_auth": True,
        "with_ntlm": True,
        "with_ntlm_wb": True,
        "with_cookies": True,
        "with_ipv6": True,
        "with_docs": False,
        "with_verbose_debug": True,
        "with_symbol_hiding": False,
        "with_unix_sockets": True,
    }

    generators = "cmake", "cmake_find_package_multi", "pkg_config"
    _autotools = None
    _autotools_vars = None
    _cmake = None

    @property
    def _source_subfolder(self):
        return "source_subfolder"

    @property
    def _build_subfolder(self):
        return "build_subfolder"

    @property
    def _is_msvc(self):
        return str(self.settings.compiler) in ["Visual Studio", "msvc"]

    @property
    def _is_mingw(self):
        return self.settings.os == "Windows" and self.settings.compiler == "gcc"

    @property
    def _is_win_x_android(self):
        return self.settings.os == "Android" and tools.os_info.is_windows

    @property
    def _settings_build(self):
        return getattr(self, "settings_build", self.settings)

    @property
    def _is_using_cmake_build(self):
        return self._is_msvc or self._is_win_x_android

    @property
    def _has_zstd_option(self):
        return tools.Version(self.version) >= "7.72.0"

    @property
    def _has_metalink_option(self):
        # Support for metalink was removed in version 7.78.0 https://github.com/curl/curl/pull/7176
        return tools.Version(self.version) < "7.78.0" and not self._is_using_cmake_build

    def export_sources(self):
        self.copy("CMakeLists.txt")
        self.copy("lib_Makefile_add.am")
        for patch in self.conan_data.get("patches", {}).get(self.version, []):
            self.copy(patch["patch_file"])

    def config_options(self):
        if self.settings.os == "Windows":
            del self.options.fPIC
        if not self._has_zstd_option:
            del self.options.with_zstd
        if not self._has_metalink_option:
            del self.options.with_libmetalink
        # Default options
        self.options.with_ssl = "darwinssl" if tools.is_apple_os(self.settings.os) else "openssl"

    def configure(self):
        if self.options.shared:
            del self.options.fPIC
        del self.settings.compiler.libcxx
        del self.settings.compiler.cppstd

        # These options are not used in CMake build yet
        if self._is_using_cmake_build:
            if tools.Version(self.version) < "7.75.0":
                del self.options.with_libidn
            del self.options.with_libpsl

    def requirements(self):
        if self.options.with_ssl == "openssl":
            self.requires("openssl/1.1.1m")
        elif self.options.with_ssl == "wolfssl":
            self.requires("wolfssl/4.8.1")
        elif self.options.with_ssl == "mbedtls":
            self.requires("mbedtls/2.25.0")
        if self.options.with_nghttp2:
            self.requires("libnghttp2/1.45.1")
        if self.options.with_libssh2:
            self.requires("libssh2/1.10.0")
        if self.options.with_zlib:
            self.requires("zlib/1.2.11")
        if self.options.with_brotli:
            self.requires("brotli/1.0.9")
        if self.options.get_safe("with_zstd"):
            self.requires("zstd/1.5.2")
        if self.options.with_c_ares:
            self.requires("c-ares/1.17.2")

    def validate(self):
        if self.options.with_ssl == "schannel" and self.settings.os != "Windows":
            raise ConanInvalidConfiguration("schannel only suppported on Windows.")
        if self.options.with_ssl == "darwinssl" and not tools.is_apple_os(self.settings.os):
            raise ConanInvalidConfiguration("darwinssl only suppported on Apple like OS (Macos, iOS, watchOS or tvOS).")
        if self.options.with_ssl == "wolfssl" and self._is_using_cmake_build and tools.Version(self.version) < "7.70.0":
            raise ConanInvalidConfiguration("Before 7.70.0, libcurl has no wolfssl support for Visual Studio or \"Windows to Android cross compilation\"")
        if self.options.with_ssl == "openssl":
            if self.options.with_ntlm and self.options["openssl"].no_des:
                raise ConanInvalidConfiguration("option with_ntlm=True requires openssl:no_des=False")

    def build_requirements(self):
        if self._is_using_cmake_build:
            if self._is_win_x_android:
                self.build_requires("ninja/1.10.2")
        else:
            self.build_requires("libtool/2.4.6")
            self.build_requires("pkgconf/1.7.4")
            if self._settings_build.os == "Windows" and not tools.get_env("CONAN_BASH_PATH"):
                self.build_requires("msys2/cci.latest")

    def source(self):
        tools.get(**self.conan_data["sources"][self.version],
                  destination=self._source_subfolder, strip_root=True)
        tools.download("https://curl.haxx.se/ca/cacert.pem", "cacert.pem", verify=True)

    # TODO: remove imports once rpath of shared libs of libcurl dependencies fixed on macOS
    def imports(self):
        # Copy shared libraries for dependencies to fix DYLD_LIBRARY_PATH problems
        #
        # Configure script creates conftest that cannot execute without shared openssl binaries.
        # Ways to solve the problem:
        # 1. set *LD_LIBRARY_PATH (works with Linux with RunEnvironment
        #     but does not work on OS X 10.11 with SIP)
        # 2. copying dylib's to the build directory (fortunately works on OS X)
        if self.settings.os == "Macos":
            self.copy("*.dylib*", dst=self._source_subfolder, keep_path=False)

    def build(self):
        self._patch_sources()
        if self._is_using_cmake_build:
            self._build_with_cmake()
        else:
            self._build_with_autotools()

    def _patch_sources(self):
        for patch in self.conan_data.get("patches", {}).get(self.version, []):
            tools.patch(**patch)
        self._patch_misc_files()
        self._patch_autotools()
        self._patch_cmake()

    def _patch_misc_files(self):
        if self.options.with_largemaxwritesize:
            tools.replace_in_file(os.path.join(self._source_subfolder, "include", "curl", "curl.h"),
                                  "define CURL_MAX_WRITE_SIZE 16384",
                                  "define CURL_MAX_WRITE_SIZE 10485760")

        # https://github.com/curl/curl/issues/2835
        # for additional info, see this comment https://github.com/conan-io/conan-center-index/pull/1008#discussion_r386122685
        if self.settings.compiler == "apple-clang" and self.settings.compiler.version == "9.1":
            if self.options.with_ssl == "darwinssl":
                tools.replace_in_file(os.path.join(self._source_subfolder, "lib", "vtls", "sectransp.c"),
                                      "#define CURL_BUILD_MAC_10_13 MAC_OS_X_VERSION_MAX_ALLOWED >= 101300",
                                      "#define CURL_BUILD_MAC_10_13 0")

    def _patch_autotools(self):
        if self._is_using_cmake_build:
            return

        # Disable curl tool for these reasons:
        # - link errors if mingw shared or iOS/tvOS/watchOS
        # - it makes recipe consistent with CMake build where we don't build curl tool
        top_makefile = os.path.join(self._source_subfolder, "Makefile.am")
        tools.replace_in_file(top_makefile, "SUBDIRS = lib src", "SUBDIRS = lib")
        tools.replace_in_file(top_makefile, "include src/Makefile.inc", "")

        if self._is_mingw:
            # patch for zlib naming in mingw
            if self.options.with_zlib:
                configure_ac = os.path.join(self._source_subfolder, "configure.ac")
                zlib_name = self.deps_cpp_info["zlib"].libs[0]
                tools.replace_in_file(configure_ac,
                                      "AC_CHECK_LIB(z,",
                                      "AC_CHECK_LIB({},".format(zlib_name))
                tools.replace_in_file(configure_ac,
                                      "-lz ",
                                      "-l{} ".format(zlib_name))

            if self.options.shared:
                # patch for shared mingw build
                lib_makefile = os.path.join(self._source_subfolder, "lib", "Makefile.am")
                tools.replace_in_file(lib_makefile,
                                      "noinst_LTLIBRARIES = libcurlu.la",
                                      "")
                tools.replace_in_file(lib_makefile,
                                      "noinst_LTLIBRARIES =",
                                      "")
                tools.replace_in_file(lib_makefile,
                                      "lib_LTLIBRARIES = libcurl.la",
                                      "noinst_LTLIBRARIES = libcurl.la")
                # add directives to build dll
                # used only for native mingw-make
                if not tools.cross_building(self.settings):
                    added_content = tools.load("lib_Makefile_add.am")
                    tools.save(lib_makefile, added_content, append=True)

    def _patch_cmake(self):
        if not self._is_using_cmake_build:
            return
        # Custom findZstd.cmake file relies on pkg-config file, make sure that it's consumed on all platforms
        if self._has_zstd_option:
            tools.replace_in_file(os.path.join(self._source_subfolder, "CMake", "FindZstd.cmake"),
                                  "if(UNIX)", "if(TRUE)")
        # TODO: check this patch, it's suspicious
        tools.replace_in_file(os.path.join(self._source_subfolder, "CMakeLists.txt"),
                              "include(CurlSymbolHiding)", "")

    def _get_configure_command_args(self):
        yes_no = lambda v: "yes" if v else "no"
        params = [
            "--with-libidn2={}".format(yes_no(self.options.with_libidn)),
            "--with-librtmp={}".format(yes_no(self.options.with_librtmp)),
            "--with-libpsl={}".format(yes_no(self.options.with_libpsl)),
            "--with-schannel={}".format(yes_no(self.options.with_ssl == "schannel")),
            "--with-secure-transport={}".format(yes_no(self.options.with_ssl == "darwinssl")),
            "--with-brotli={}".format(yes_no(self.options.with_brotli)),
            "--enable-shared={}".format(yes_no(self.options.shared)),
            "--enable-static={}".format(yes_no(not self.options.shared)),
            "--enable-dict={}".format(yes_no(self.options.with_dict)),
            "--enable-file={}".format(yes_no(self.options.with_file)),
            "--enable-ftp={}".format(yes_no(self.options.with_ftp)),
            "--enable-gopher={}".format(yes_no(self.options.with_gopher)),
            "--enable-http={}".format(yes_no(self.options.with_http)),
            "--enable-imap={}".format(yes_no(self.options.with_imap)),
            "--enable-ldap={}".format(yes_no(self.options.with_ldap)),
            "--enable-mqtt={}".format(yes_no(self.options.with_mqtt)),
            "--enable-pop3={}".format(yes_no(self.options.with_pop3)),
            "--enable-rtsp={}".format(yes_no(self.options.with_rtsp)),
            "--enable-smb={}".format(yes_no(self.options.with_smb)),
            "--enable-smtp={}".format(yes_no(self.options.with_smtp)),
            "--enable-telnet={}".format(yes_no(self.options.with_telnet)),
            "--enable-tftp={}".format(yes_no(self.options.with_tftp)),
            "--enable-debug={}".format(yes_no(self.settings.build_type == "Debug")),
            "--enable-ares={}".format(yes_no(self.options.with_c_ares)),
            "--enable-threaded-resolver={}".format(yes_no(self.options.with_c_ares)),
            "--enable-cookies={}".format(yes_no(self.options.with_cookies)),
            "--enable-ipv6={}".format(yes_no(self.options.with_ipv6)),
            "--enable-manual={}".format(yes_no(self.options.with_docs)),
            "--enable-verbose={}".format(yes_no(self.options.with_verbose_debug)),
            "--enable-symbol-hiding={}".format(yes_no(self.options.with_symbol_hiding)),
            "--enable-unix-sockets={}".format(yes_no(self.options.with_unix_sockets)),
        ]
        if self.options.with_ssl == "openssl":
            params.append("--with-ssl={}".format(tools.unix_path(self.deps_cpp_info["openssl"].rootpath)))
        else:
            params.append("--without-ssl")
        if self.options.with_ssl == "wolfssl":
            params.append("--with-wolfssl={}".format(tools.unix_path(self.deps_cpp_info["wolfssl"].rootpath)))
        else:
            params.append("--without-wolfssl")
        if self.options.with_ssl == "mbedtls":
            params.append("--with-mbedtls={}".format(tools.unix_path(self.deps_cpp_info["mbedtls"].rootpath)))
        else:
            params.append("--without-mbedtls")

        if self.options.with_libssh2:
            params.append("--with-libssh2={}".format(tools.unix_path(self.deps_cpp_info["libssh2"].rootpath)))
        else:
            params.append("--without-libssh2")

        if self.options.with_nghttp2:
            params.append("--with-nghttp2={}".format(tools.unix_path(self.deps_cpp_info["libnghttp2"].rootpath)))
        else:
            params.append("--without-nghttp2")

        if self.options.with_zlib:
            params.append("--with-zlib={}".format(tools.unix_path(self.deps_cpp_info["zlib"].rootpath)))
        else:
            params.append("--without-zlib")

        if self._has_zstd_option:
            params.append("--with-zstd={}".format(yes_no(self.options.with_zstd)))

        if self._has_metalink_option:
            params.append("--with-libmetalink={}".format(yes_no(self.options.with_libmetalink)))

        if not self.options.with_proxy:
            params.append("--disable-proxy")

        if not self.options.with_rtsp:
            params.append("--disable-rtsp")

        if not self.options.with_crypto_auth:
            params.append("--disable-crypto-auth") # also disables NTLM in versions of curl prior to 7.78.0

        # ntlm will default to enabled if any SSL options are enabled
        if not self.options.with_ntlm:
            if tools.Version(self.version) <= "7.77.0":
                params.append("--disable-crypto-auth")
            else:
                params.append("--disable-ntlm")

        if not self.options.with_ntlm_wb:
            params.append("--disable-ntlm-wb")

        # Cross building flags
        if tools.cross_building(self.settings):
            if self.settings.os == "Linux" and "arm" in self.settings.arch:
                params.append("--host=%s" % self._get_linux_arm_host())
            elif self.settings.os == "iOS":
                params.append("--enable-threaded-resolver")
                params.append("--disable-verbose")
            elif self.settings.os == "Android":
                pass # this just works, conan is great!

        return params

    def _get_linux_arm_host(self):
        arch = None
        if self.settings.os == "Linux":
            arch = "arm-linux-gnu"
            # aarch64 could be added by user
            if "aarch64" in self.settings.arch:
                arch = "aarch64-linux-gnu"
            elif "arm" in self.settings.arch and "hf" in self.settings.arch:
                arch = "arm-linux-gnueabihf"
            elif "arm" in self.settings.arch and self._arm_version(str(self.settings.arch)) > 4:
                arch = "arm-linux-gnueabi"
        return arch

    # TODO, this should be a inner fuction of _get_linux_arm_host since it is only used from there
    # it should not polute the class namespace, since there are iOS and Android arm aritectures also
    def _arm_version(self, arch):
        version = None
        match = re.match(r"arm\w*(\d)", arch)
        if match:
            version = int(match.group(1))
        return version

    def _build_with_autotools(self):
        with tools.chdir(self._source_subfolder):
            # autoreconf
            self.run("{} -fiv".format(tools.get_env("AUTORECONF") or "autoreconf"), win_bash=tools.os_info.is_windows, run_environment=True)

            # fix generated autotools files to have relocatable binaries
            if tools.is_apple_os(self.settings.os):
                tools.replace_in_file("configure", "-install_name \\$rpath/", "-install_name @rpath/")

            self.run("chmod +x configure")

            # run configure with *LD_LIBRARY_PATH env vars it allows to pick up shared openssl
            with tools.run_environment(self):
                autotools, autotools_vars = self._configure_autotools()
                autotools.make(vars=autotools_vars)

    def _configure_autotools_vars(self):
        autotools_vars = self._autotools.vars
        # tweaks for mingw
        if self._is_mingw:
            autotools_vars["RCFLAGS"] = "-O COFF"
            if self.settings.arch == "x86":
                autotools_vars["RCFLAGS"] += " --target=pe-i386"
            else:
                autotools_vars["RCFLAGS"] += " --target=pe-x86-64"
        return autotools_vars

    def _configure_autotools(self):
        if self._autotools and self._autotools_vars:
            return self._autotools, self._autotools_vars

        self._autotools = AutoToolsBuildEnvironment(self, win_bash=tools.os_info.is_windows)

        if self.settings.os != "Windows":
            self._autotools.fpic = self.options.get_safe("fPIC", True)

        self._autotools_vars = self._configure_autotools_vars()

        # tweaks for mingw
        if self._is_mingw:
            self._autotools.defines.append("_AMD64_")

        if tools.cross_building(self) and tools.is_apple_os(self.settings.os):
            self._autotools.defines.extend(['HAVE_SOCKET', 'HAVE_FCNTL_O_NONBLOCK'])

        configure_args = self._get_configure_command_args()

        if self.settings.os == "iOS" and self.settings.arch == "x86_64":
            # please do not autodetect --build for the iOS simulator, thanks!
            self._autotools.configure(vars=self._autotools_vars, args=configure_args, build=False)
        else:
            self._autotools.configure(vars=self._autotools_vars, args=configure_args)

        return self._autotools, self._autotools_vars

    def _configure_cmake(self):
        if self._cmake:
            return self._cmake
        if self._is_win_x_android:
            self._cmake = CMake(self, generator="Ninja")
        else:
            self._cmake = CMake(self)
        self._cmake.definitions["BUILD_TESTING"] = False
        self._cmake.definitions["BUILD_CURL_EXE"] = False
        self._cmake.definitions["CURL_DISABLE_LDAP"] = not self.options.with_ldap
        self._cmake.definitions["BUILD_SHARED_LIBS"] = self.options.shared
        self._cmake.definitions["CURL_STATICLIB"] = not self.options.shared
        self._cmake.definitions["CMAKE_DEBUG_POSTFIX"] = ""
        if tools.Version(self.version) >= "7.72.0":
            self._cmake.definitions["CMAKE_USE_SCHANNEL"] = self.options.with_ssl == "schannel"
        else:
            self._cmake.definitions["CMAKE_USE_WINSSL"] = self.options.with_ssl == "schannel"
        self._cmake.definitions["CMAKE_USE_OPENSSL"] = self.options.with_ssl == "openssl"
        if tools.Version(self.version) >= "7.70.0":
            self._cmake.definitions["CMAKE_USE_WOLFSSL"] = self.options.with_ssl == "wolfssl"
        self._cmake.definitions["CMAKE_USE_MBEDTLS"] = self.options.with_ssl == "mbedtls"
        self._cmake.definitions["USE_NGHTTP2"] = self.options.with_nghttp2
        self._cmake.definitions["CURL_ZLIB"] = self.options.with_zlib
        self._cmake.definitions["CURL_BROTLI"] = self.options.with_brotli
        if self._has_zstd_option:
            self._cmake.definitions["CURL_ZSTD"] = self.options.with_zstd
        self._cmake.definitions["CMAKE_USE_LIBSSH2"] = self.options.with_libssh2
        self._cmake.definitions["ENABLE_ARES"] = self.options.with_c_ares
        self._cmake.definitions["CURL_DISABLE_PROXY"] = not self.options.with_proxy
        self._cmake.definitions["USE_LIBRTMP"] = self.options.with_librtmp
        if tools.Version(self.version) >= "7.75.0":
            self._cmake.definitions["USE_LIBIDN2"] = self.options.with_libidn
        self._cmake.definitions["CURL_DISABLE_RTSP"] = not self.options.with_rtsp
        self._cmake.definitions["CURL_DISABLE_CRYPTO_AUTH"] = not self.options.with_crypto_auth

        # Also disables NTLM_WB if set to false
        if not self.options.with_ntlm:
            if tools.Version(self.version) <= "7.77.0":
                self._cmake.definitions["CURL_DISABLE_CRYPTO_AUTH"] = True
            else:
                self._cmake.definitions["CURL_DISABLE_NTLM"] = True
        self._cmake.definitions["NTLM_WB_ENABLED"] = self.options.with_ntlm_wb

        self._cmake.configure(build_folder=self._build_subfolder)
        return self._cmake

    def _build_with_cmake(self):
        cmake = self._configure_cmake()
        cmake.build()

    def package(self):
        self.copy("COPYING", dst="licenses", src=self._source_subfolder)
        self.copy("cacert.pem", dst="res")
        if self._is_using_cmake_build:
            cmake = self._configure_cmake()
            cmake.install()
            tools.rmdir(os.path.join(self.package_folder, "lib", "cmake"))
        else:
            with tools.run_environment(self):
                with tools.chdir(self._source_subfolder):
                    autotools, autotools_vars = self._configure_autotools()
                    autotools.install(vars=autotools_vars)
            tools.rmdir(os.path.join(self.package_folder, "share"))
            for la_file in glob.glob(os.path.join(self.package_folder, "lib", "*.la")):
                os.remove(la_file)
            if self._is_mingw and self.options.shared:
                # Handle only mingw libs
                self.copy(pattern="*.dll", dst="bin", keep_path=False)
                self.copy(pattern="*.dll.a", dst="lib", keep_path=False)
                self.copy(pattern="*.lib", dst="lib", keep_path=False)
        tools.rmdir(os.path.join(self.package_folder, "lib", "pkgconfig"))

    def package_info(self):
        self.cpp_info.set_property("cmake_file_name", "CURL")
        self.cpp_info.set_property("cmake_target_name", "CURL::libcurl")
        self.cpp_info.set_property("cmake_find_mode", "both")
        self.cpp_info.set_property("pkg_config_name", "libcurl")

        if self._is_msvc:
            self.cpp_info.components["curl"].libs = ["libcurl_imp"] if self.options.shared else ["libcurl"]
        else:
            self.cpp_info.components["curl"].libs = ["curl"]
            if self.settings.os in ["Linux", "FreeBSD"]:
                if self.options.with_libidn:
                    self.cpp_info.components["curl"].libs.append("idn")
                if self.options.with_librtmp:
                    self.cpp_info.components["curl"].libs.append("rtmp")

        if self.settings.os in ["Linux", "FreeBSD"]:
            self.cpp_info.components["curl"].system_libs = ["rt", "pthread"]
        elif self.settings.os == "Windows":
            # used on Windows for VS build, native and cross mingw build
            self.cpp_info.components["curl"].system_libs = ["ws2_32"]
            if self.options.with_ldap:
                self.cpp_info.components["curl"].system_libs.append("wldap32")
            if self.options.with_ssl == "schannel":
                self.cpp_info.components["curl"].system_libs.append("crypt32")
        elif tools.is_apple_os(self.settings.os):
            if tools.Version(self.version) >= "7.77.0":
                self.cpp_info.components["curl"].frameworks.append("SystemConfiguration")
            if self.options.with_ldap:
                self.cpp_info.components["curl"].system_libs.append("ldap")
            if self.options.with_ssl == "darwinssl":
                self.cpp_info.components["curl"].frameworks.extend(["CoreFoundation", "Security"])

        if self._is_mingw:
            # provide pthread for dependent packages
            self.cpp_info.components["curl"].cflags.append("-pthread")
            self.cpp_info.components["curl"].exelinkflags.append("-pthread")
            self.cpp_info.components["curl"].sharedlinkflags.append("-pthread")

        if not self.options.shared:
            self.cpp_info.components["curl"].defines.append("CURL_STATICLIB=1")

        if self.options.with_ssl == "openssl":
            self.cpp_info.components["curl"].requires.append("openssl::openssl")
        if self.options.with_ssl == "wolfssl":
            self.cpp_info.components["curl"].requires.append("wolfssl::wolfssl")
        if self.options.with_ssl == "mbedtls":
            self.cpp_info.components["curl"].requires.append("mbedtls::mbedtls")
        if self.options.with_nghttp2:
            self.cpp_info.components["curl"].requires.append("libnghttp2::libnghttp2")
        if self.options.with_libssh2:
            self.cpp_info.components["curl"].requires.append("libssh2::libssh2")
        if self.options.with_zlib:
            self.cpp_info.components["curl"].requires.append("zlib::zlib")
        if self.options.with_brotli:
            self.cpp_info.components["curl"].requires.append("brotli::brotli")
        if self.options.get_safe("with_zstd"):
            self.cpp_info.components["curl"].requires.append("zstd::zstd")
        if self.options.with_c_ares:
            self.cpp_info.components["curl"].requires.append("c-ares::c-ares")

        # TODO: to remove in conan v2 once cmake_find_package* generators removed
        self.cpp_info.names["cmake_find_package"] = "CURL"
        self.cpp_info.names["cmake_find_package_multi"] = "CURL"
        self.cpp_info.components["curl"].names["cmake_find_package"] = "libcurl"
        self.cpp_info.components["curl"].names["cmake_find_package_multi"] = "libcurl"
        self.cpp_info.components["curl"].set_property("cmake_target_name", "CURL::libcurl")
        self.cpp_info.components["curl"].set_property("pkg_config_name", "libcurl")
