#pragma once
// ============================================================================
// CvLoader -- Runtime discovery and pre-loading of OpenCV DLLs
//
// OpenCV is normally import-linked (opencv_world4130.lib), but the DLLs
// must be discoverable at process load time.  CvLoader ensures the correct
// DLL is found by:
//   1. Searching the ANSCENTER shared directory for versioned candidates
//   2. Injecting the directory into the DLL search path
//   3. Pre-loading the DLL so dependent modules resolve it correctly
//
// Companion modules (opencv_img_hash, opencv_videoio_ffmpeg) are also
// pre-loaded when found alongside the main opencv_world DLL.
// ============================================================================

#include "ANSLibsLoader.h"   // ANSLIBS_API
#include "DynLibUtils.h"     // LibHandle

#include <string>
#include <vector>
#include <mutex>

// ============================================================================
struct ANSLIBS_API CvInfo
{
    std::string dllPath;        // Full path to loaded opencv_world DLL
    std::string version;        // e.g. "4.13.0"
    int         versionCode = 0;// e.g. 4130
    bool        loaded = false;
};

// ============================================================================
class ANSLIBS_API CvLoader
{
public:
    /// Discover and pre-load OpenCV DLLs.
    /// Safe to call multiple times -- subsequent calls are no-ops.
    /// @param shared_dir  Directory to search first (default: ANSCENTER shared).
    /// @param verbose     Print discovery results to stdout.
    /// @returns Reference to the discovery result.
    [[nodiscard]] static const CvInfo& Initialize(
        const std::string& shared_dir = ANSCENTER::DynLib::DEFAULT_SHARED_DIR,
        bool verbose = true);

    /// Release pre-loaded library handles.
    static void Shutdown();

    /// Query current state.
    [[nodiscard]] static const CvInfo& Current() noexcept { return s_info; }
    [[nodiscard]] static bool IsInitialized()    noexcept { return s_initialized; }

private:
    /// Build candidate DLL names, newest first.
    static std::vector<std::string> CvWorldCandidates(const std::string& shared_dir);
    static std::vector<std::string> CvImgHashCandidates(const std::string& shared_dir);

    static std::mutex s_mutex;
    static bool       s_initialized;
    static CvInfo     s_info;
    static LibHandle  s_hCvWorld;
    static LibHandle  s_hCvImgHash;
};
