# ------------------------------------------------------------------------------
#        Mobile Robot Programming Toolkit (MRPT)
#
# Copyright (c) 2005-2026, Jose Luis Blanco-Claraco, contributors (see Git history)
# All rights reserved.
# SPDX-License-Identifier: BSD-3-Clause
# ------------------------------------------------------------------------------

cmake_minimum_required(VERSION 3.16)

# Tell CMake we'll use C++ for use in its tests/flags
project(mrpt_io LANGUAGES C CXX)

# MRPT CMake scripts: "mrpt_xxx()"
find_package(mrpt_common REQUIRED)
find_package(mrpt_system REQUIRED)

include(./cmake/script_zlib.cmake REQUIRED)        # Check for zlib

# Embedded version of zlib, if really needed:
# Only include zlib if not available as system library OR it's already in wxWidgets:
if(CMAKE_MRPT_HAS_ZLIB)
  if(CMAKE_MRPT_HAS_ZLIB_SYSTEM_IS_WX OR NOT CMAKE_MRPT_HAS_ZLIB_SYSTEM)
    include_directories(${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/zlib/)
    if(NOT MSVC OR NOT CMAKE_MRPT_HAS_ZLIB_SYSTEM_IS_WX)
      set(io_EXTRA_SRCS
        3rdparty/zlib/adler32.c
        3rdparty/zlib/compress.c
        3rdparty/zlib/crc32.c
        3rdparty/zlib/deflate.c
        3rdparty/zlib/gzclose.c
        3rdparty/zlib/gzlib.c
        3rdparty/zlib/gzread.c
        3rdparty/zlib/gzwrite.c
        3rdparty/zlib/infback.c
        3rdparty/zlib/inffast.c
        3rdparty/zlib/inflate.c
        3rdparty/zlib/inftrees.c
        3rdparty/zlib/trees.c
        3rdparty/zlib/uncompr.c
        3rdparty/zlib/zutil.c
      )
    endif()
  endif()
endif()


# define lib:
set(LIB_SOURCES
  src/CCompressedInputStream.cpp
  src/CCompressedOutputStream.cpp
  src/CFileGZInputStream.cpp
  src/CFileGZOutputStream.cpp
  src/CFileInputStream.cpp
  src/CFileOutputStream.cpp
  src/CFileStream.cpp
  src/CMemoryStream.cpp
  src/CPipe.cpp
  src/CStream.cpp
  src/CTextFileLinesParser.cpp
  src/detect_compression.cpp
  src/lazy_load_path.cpp
  src/vector_loadsave.cpp
  src/zip.cpp
)

set(LIB_UNIT_TEST_SOURCES
  tests/CFileStream_unittest.cpp
  tests/CMemoryStream_unittest.cpp
  tests/CPipe_unittest.cpp
  tests/CTextFileLinesParser_unittest.cpp
  tests/vector_loadsave_unittest.cpp
  tests/zip_unittest.cpp
  tests/vector_loadsave_extra_unittest.cpp
  tests/CStream_unittest.cpp
  tests/CMemoryStream_extra_unittest.cpp
  tests/CPipe_extra_unittest.cpp
  tests/CCompressedStreams_extra_unittest.cpp
  tests/file_streams_unittest.cpp
  tests/compression_unittest.cpp
  tests/misc_io_unittest.cpp
)

# These tests are moved to mrpt_viz since that's the lowest-level module that includes all dependencies.
#src/CSerializable_unittest.cpp
#src/bimap_serialize_unittest.cpp
#src/stl_serialize_unittest.cpp
#src/CFileGZStreams_unittest.cpp 


set(LIB_PUBLIC_HEADERS
  include/mrpt/io/CCompressedInputStream.h
  include/mrpt/io/CCompressedOutputStream.h
  include/mrpt/io/CTextFileLinesParser.h
  include/mrpt/io/CFileGZOutputStream.h
  include/mrpt/io/zip.h
  include/mrpt/io/CFileInputStream.h
  include/mrpt/io/CPipe.h
  include/mrpt/io/registerAllClasses.h
  include/mrpt/io/CStream.h
  include/mrpt/io/detect_compression.h
  include/mrpt/io/vector_loadsave.h
  include/mrpt/io/lazy_load_path.h
  include/mrpt/io/CFileStream.h
  include/mrpt/io/CFileGZInputStream.h
  include/mrpt/io/csv.h
  include/mrpt/io/CFileOutputStream.h
  include/mrpt/io/open_flags.h
  include/mrpt/io/CMemoryStream.h
)

mrpt_add_library(
  TARGET ${PROJECT_NAME}
  SOURCES ${LIB_SOURCES} ${LIB_PUBLIC_HEADERS}
    # Add the optional extra sources (bundled zlib):
    ${io_EXTRA_SRCS}
  UNIT_TEST_SOURCES ${LIB_UNIT_TEST_SOURCES}
  PUBLIC_LINK_LIBRARIES
    mrpt::mrpt_system
#  PRIVATE_LINK_LIBRARIES
  CMAKE_DEPENDENCIES
    mrpt_system
  # Other imported targets:
)


find_path(ZSTD_INCLUDE_DIRS
  NAMES zstd.h
  HINTS ${zstd_ROOT_DIR}/include)

find_library(ZSTD_LIBRARIES
  NAMES zstd
  HINTS ${zstd_ROOT_DIR}/lib)

target_include_directories(${PROJECT_NAME} PRIVATE ${ZSTD_INCLUDE_DIRS})
target_link_libraries(${PROJECT_NAME} PRIVATE ${ZSTD_LIBRARIES})


if(CMAKE_MRPT_HAS_ZLIB)
  if(NOT CMAKE_MRPT_HAS_ZLIB_SYSTEM_IS_WX AND CMAKE_MRPT_HAS_ZLIB_SYSTEM)
      target_link_libraries(${PROJECT_NAME} PRIVATE ${ZLIB_LIBRARIES})
    target_include_directories(${PROJECT_NAME} PRIVATE ${ZLIB_INCLUDE_DIR})
  endif()

  if (NOT "${io_EXTRA_SRCS}" STREQUAL "")
    # The bundled zconf.h only includes <unistd.h> (lseek, read, etc.) if
    # HAVE_UNISTD_H is defined; modern compilers reject implicit declarations.
    include(CheckIncludeFile)
    check_include_file(unistd.h HAVE_UNISTD_H)
    if (HAVE_UNISTD_H)
      set(extra_flags2_ "-DHAVE_UNISTD_H")
    endif()

    # Strip gcov instrumentation from bundled zlib sources; coverage of
    # third-party code is noise, not signal.
    if(ENABLE_COVERAGE)
      set(extra_flags2_ "${extra_flags2_} -fno-profile-arcs -fno-test-coverage")
    endif()
    set_source_files_properties(
      ${io_EXTRA_SRCS}
      PROPERTIES COMPILE_FLAGS "${extra_flags_} ${extra_flags2_}"
      )
    unset(extra_flags_)
    unset(extra_flags2_)
  endif()
endif()

# Use wxWidgets version of libzip (gz* functions)
if(MSVC AND CMAKE_MRPT_HAS_WXWIDGETS)
    target_link_libraries(${PROJECT_NAME} PRIVATE imp_wxwidgets)
endif()

# Python bindings
mrpt_add_python_module(io
  python_bindings/mrpt_io_py.cpp
)

# archiveFrom() binds mrpt_serialization's CArchive to mrpt_io streams, so only
# the Python module (not the C++ library) needs mrpt_serialization.
if (TARGET _bindings)
  find_package(mrpt_serialization REQUIRED)
  target_link_libraries(_bindings PRIVATE mrpt::mrpt_serialization)
endif()

mrpt_add_python_binding_test(io
  SCRIPT ${CMAKE_CURRENT_SOURCE_DIR}/tests/python_io_test.py
)
