# This file is part of PyCPL the ESO CPL Python language bindings
# Copyright (C) 2020-2026 European Southern Observatory
# 
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
# 
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.

#[=======================================================================[.rst:
FindCEXT
--------

Find the ESO C Library Extensions library and headers. The
module can be configured using the following variables:

    CEXT_ROOT:    Location where CEXT is installed

or the corresponding environment variable CEXT_ROOT.

The module also takes into account the environment variable CEXTDIR.
If it is set it should point to the location of the CEXT installation.
Using the environment variable is equivalent to setting the option
CEXT_ROOT. However, if both, CEXT_ROOT and CEXTDIR, are set the
CEXT_ROOT variable setting takes precedence.

Imported Targets
^^^^^^^^^^^^^^^^

This module provides the following imported targets, if found:

``CEXT::cext``
  The CEXT library.

Result Variables
^^^^^^^^^^^^^^^^

This module defines the following variables:

``CEXT_FOUND``
  "True" if both, CEXT header files and the CEXT library were found.

``CEXT_INCLUDE_DIR``
  Path where the CEXT header files are located.

``CEXT_LIBRARY``
  Path where the CEXT library is located.

``CEXT_VERSION``
  Full version string of the CEXT library.

``CEXT_VERSION_MAJOR``
  Major version number of the CEXT library.

``CEXT_VERSION_MINOR``
  Minor version number of the CEXT library.

``CEXT_VERSION_PATCH``
  Patch version number of the CEXT library.

Cache Variables
^^^^^^^^^^^^^^^

The following cache variables may also be set:

``CEXT_INCLUDE_DIR``
  Path where the CEXT header files are located.

``CEXT_LIBRARY``
  Path where the CEXT library is located.
#]=======================================================================]

cmake_policy(VERSION 3.12)

include(FindPackageHandleStandardArgs)

if(NOT PkgConfig_FOUND)
    find_package(PkgConfig QUIET)
endif()

# For backwards compatibility also honor the CEXTDIR environment variable.
if(NOT CEXT_ROOT AND (NOT "$ENV{CEXTDIR}" STREQUAL ""))
    set(CEXT_ROOT "$ENV{CEXTDIR}")
endif()

# Use pkg-config to look for a standard CEXT installation. The results
# will only be used if no installation root was configured by setting
# CEXT_ROOT. Setting the documented output variables is deferred, as
# functions like find_path()/find_library() perform the search only if
# the target variable is either not set, NOTFOUND, or ends in -NOTFOUND.
if(PkgConfig_FOUND)
    pkg_check_modules(PC_CEXT QUIET IMPORTED_TARGET GLOBAL
                    cext)
endif()

# If CEXT_ROOT is set, try to find a CEXT installation in that path.
# An explicitly provided CEXT_ROOT means that any CEXT installation
# in that path will take pecedence over a compatible CEXT installation
# that would have been found by pkg-config (see below). 
if(CEXT_ROOT AND NOT CEXT_ROOT STREQUAL "")
    # Search for the header files
    find_path(CEXT_INCLUDE_DIR
            NAMES cxtypes.h
            HINTS ${CEXT_ROOT}/include)
    mark_as_advanced(CEXT_INCLUDE_DIR)

    # Search for the component libraries. Also look into the 'lib64'
    # directoy when searching for the libraries.
    set(FIND_LIBRARY_USE_LIB64_PATHS True)
    find_library(CEXT_LIBRARY
                NAMES cext
                HINTS ${CEXT_ROOT}/lib)
    mark_as_advanced(CEXT_LIBRARY)
    if(CEXT_LIBRARY)
        set(CEXT_FOUND True)
    endif()

    # Determine the library version from the header files.
    if(CEXT_INCLUDE_DIR)
        if(EXISTS ${CEXT_INCLUDE_DIR}/cxversion.h)
            file(STRINGS "${CEXT_INCLUDE_DIR}/cxversion.h"
                cext_version
                REGEX "^[\t ]*#define[\t ]+CX_VERSION_STRING[\t ]+\"[0-9]+\.[0-9]+.*\"")
            string(REGEX REPLACE
                "^[\t ]*#define[\t ]+CX_VERSION_STRING[\t ]+\"([0-9]+\.[0-9][^a-z \"]*).*" "\\1"
                CEXT_VERSION ${cext_version})
            unset(cext_version)
        else()
            message(AUTHOR_WARNING, "CEXT was found, but no version information is available (older than 1.3.2)! Assuming minimum required version!")
            set(CEXT_VERSION "1.2.6")
        endif()
    endif()
endif()

# If CEXT_ROOT is provided assume that any installation found there takes
# precedence, even if no CEXT installation is present and pkg-config would
# return a compatible system installation. Thus a pkg-config provided
# CEXT installation is only used if no CEXT installation was found.
if(PC_CEXT_FOUND AND NOT CEXT_FOUND)
    set(CEXT_VERSION "${PC_CEXT_VERSION}")
    set(CEXT_INCLUDE_DIR "${PC_CEXT_INCLUDE_DIRS}")
    set(CEXT_LIBRARY "${PC_CEXT_LINK_LIBRARIES}")
    set(CEXT_FOUND True)
endif()

# Decompose the version string into major, minor and patch version numbers
set(cext_version_regex "([0-9]+)\.([0-9]+)(\.([0-9]+))?.*")
string(REGEX MATCH ${cext_version_regex}
       cext_version_string "${CEXT_VERSION}")
set(CEXT_VERSION_MAJOR ${CMAKE_MATCH_1})
set(CEXT_VERSION_MINOR ${CMAKE_MATCH_2})
if(NOT "${CMAKE_MATCH_4}" STREQUAL "")
    set(CEXT_VERSION_PATCH ${CMAKE_MATCH_4})
endif()
unset(cext_version_string)
unset(cext_version_regex)

find_package_handle_standard_args(CEXT
                                  REQUIRED_VARS CEXT_INCLUDE_DIR
                                  VERSION_VAR CEXT_VERSION)

if(CEXT_FOUND)
    if(NOT TARGET CEXT::cext)
        add_library(CEXT::cext UNKNOWN IMPORTED)
        set_target_properties(CEXT::cext PROPERTIES
                              INTERFACE_INCLUDE_DIRECTORIES "${CEXT_INCLUDE_DIR}")
        if(EXISTS "${CEXT_LIBRARY}")
            set_target_properties(CEXT::cext PROPERTIES
                                  IMPORTED_LINK_INTERFACE_LANGUAGES "C"
                                  IMPORTED_LOCATION ${CEXT_LIBRARY})
        endif()
    endif()
endif()
