#ifndef _AI_UTILS_H
#define _AI_UTILS_H

#include <vector>
#include <iostream>
#include <fstream>
#include <sstream>
#include <chrono>
#include <string>
#include <regex>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include "kpu.h"
#include "k_video_comm.h"
#include "mpi_sys_api.h"

using cv::Mat;
using std::cout;
using std::endl;
using std::ifstream;
using std::vector;

//------------------------------------------------------------------------------
// ScopedTiming: A lightweight timing utility to measure execution duration
// Automatically starts timing upon construction and reports elapsed time
// when going out of scope (RAII style).
//
// Example usage:
//   {
//       PROFILE_SCOPE("Image Preprocessing", debug_mode);
//       preprocess_image();
//   } // Automatically prints "Image Preprocessing took XXX ms" if debug_mode == true
//------------------------------------------------------------------------------

struct ScopedTiming {
    std::chrono::steady_clock::time_point start;
    std::string name;
    bool enabled;

    ScopedTiming(const char* n, bool e = true)
        : start(std::chrono::steady_clock::now()), name(n), enabled(e) {}

    ScopedTiming(const std::string& n, bool e = true)
        : start(std::chrono::steady_clock::now()), name(n), enabled(e) {}

    ~ScopedTiming() {
        if (enabled) {
            auto end = std::chrono::steady_clock::now();
            double ms = std::chrono::duration<double, std::milli>(end - start).count();
            std::cout << "[PROFILE] " << name << " took " << ms << " ms\n";
        }
    }
};

//--------------------------------------------------
// Cross-platform function signature macro
//--------------------------------------------------
#if defined(__GNUC__) || defined(__clang__)
#define CURRENT_FUNCTION __PRETTY_FUNCTION__
#elif defined(_MSC_VER)
#define CURRENT_FUNCTION __FUNCSIG__
#else
#define CURRENT_FUNCTION __func__
#endif

//--------------------------------------------------
// Helper to extract "Class::method" from full signature
//--------------------------------------------------
inline std::string short_func_name(const std::string& pretty) {
    std::regex re(R"((\w+::\w+)\s*\(.*\))");
    std::smatch m;
    if (std::regex_search(pretty, m, re))
        return m[1];
    return pretty;
}

//--------------------------------------------------
// Macros for profiling
//--------------------------------------------------
#define CONCAT_DETAIL(x, y) x##y
#define CONCAT(x, y) CONCAT_DETAIL(x, y)

#define PROFILE_SCOPE(name, debug_mode) \
    ScopedTiming CONCAT(_timing_, __LINE__)(name, debug_mode)

#define PROFILE_SCOPE_AUTO(debug_mode) \
    ScopedTiming CONCAT(_timing_, __LINE__)(short_func_name(CURRENT_FUNCTION), debug_mode)


/**
 * @brief Color palette (80 predefined colors).
 *        If the number of classes exceeds 80, colors are reused cyclically.
 */
const std::vector<cv::Scalar> color_four = {
    cv::Scalar(60, 20, 220, 127),
    cv::Scalar(32, 11, 119, 127),
    cv::Scalar(142, 0, 0, 127),
    cv::Scalar(230, 0, 0, 127),
    cv::Scalar(228, 0, 106, 127),
    cv::Scalar(100, 60, 0, 127),
    cv::Scalar(100, 80, 0, 127),
    cv::Scalar(70, 0, 0, 127),
    cv::Scalar(192, 0, 0, 127),
    cv::Scalar(30, 170, 250, 127),
    cv::Scalar(30, 170, 100, 127),
    cv::Scalar(0, 220, 220, 127),
    cv::Scalar(175, 116, 175, 127),
    cv::Scalar(30, 0, 250, 127),
    cv::Scalar(42, 42, 165, 127),
    cv::Scalar(255, 77, 255, 127),
    cv::Scalar(252, 226, 0, 127),
    cv::Scalar(255, 182, 182, 127),
    cv::Scalar(0, 82, 0, 127),
    cv::Scalar(157, 166, 120, 127),
    cv::Scalar(0, 76, 110, 127),
    cv::Scalar(255, 57, 174, 127),
    cv::Scalar(0, 100, 199, 127),
    cv::Scalar(118, 0, 72, 127),
    cv::Scalar(240, 179, 255, 127),
    cv::Scalar(92, 125, 0, 127),
    cv::Scalar(151, 0, 209, 127),
    cv::Scalar(182, 208, 188, 127),
    cv::Scalar(176, 220, 0, 127),
    cv::Scalar(164, 99, 255, 127),
    cv::Scalar(73, 0, 92, 127),
    cv::Scalar(255, 129, 133, 127),
    cv::Scalar(255, 180, 78, 127),
    cv::Scalar(0, 228, 0, 127),
    cv::Scalar(243, 255, 174, 127),
    cv::Scalar(255, 89, 45, 127),
    cv::Scalar(103, 134, 134, 127),
    cv::Scalar(174, 148, 145, 127),
    cv::Scalar(186, 208, 255, 127),
    cv::Scalar(255, 226, 197, 127),
    cv::Scalar(1, 134, 171, 127),
    cv::Scalar(54, 63, 109, 127),
    cv::Scalar(255, 138, 207, 127),
    cv::Scalar(95, 0, 151, 127),
    cv::Scalar(61, 80, 9, 127),
    cv::Scalar(51, 105, 84, 127),
    cv::Scalar(105, 65, 74, 127),
    cv::Scalar(102, 196, 166, 127),
    cv::Scalar(210, 195, 208, 127),
    cv::Scalar(65, 109, 255, 127),
    cv::Scalar(149, 143, 0, 127),
    cv::Scalar(194, 0, 179, 127),
    cv::Scalar(106, 99, 209, 127),
    cv::Scalar(0, 121, 5, 127),
    cv::Scalar(205, 255, 227, 127),
    cv::Scalar(208, 186, 147, 127),
    cv::Scalar(1, 69, 153, 127),
    cv::Scalar(161, 95, 3, 127),
    cv::Scalar(0, 255, 163, 127),
    cv::Scalar(170, 0, 119, 127),
    cv::Scalar(199, 182, 0, 127),
    cv::Scalar(120, 165, 0, 127),
    cv::Scalar(88, 130, 183, 127),
    cv::Scalar(0, 32, 95, 127),
    cv::Scalar(135, 114, 130, 127),
    cv::Scalar(133, 129, 110, 127),
    cv::Scalar(118, 74, 166, 127),
    cv::Scalar(185, 142, 219, 127),
    cv::Scalar(114, 210, 79, 127),
    cv::Scalar(62, 90, 178, 127),
    cv::Scalar(15, 70, 65, 127),
    cv::Scalar(115, 167, 127, 127),
    cv::Scalar(106, 105, 59, 127),
    cv::Scalar(45, 108, 142, 127),
    cv::Scalar(0, 172, 196, 127),
    cv::Scalar(80, 54, 95, 127),
    cv::Scalar(255, 76, 128, 127),
    cv::Scalar(1, 57, 201, 127),
    cv::Scalar(122, 0, 246, 127),
    cv::Scalar(208, 162, 191, 127)
};


typedef struct FrameCHWSize
{
    size_t height;
    size_t width;
    size_t channel;
} FrameCHWSize;

// ---------------------- Utility Functions ------------------------------------

/**
 * @brief Get a color vector for N classes.
 * @param num_classes Number of object classes.
 * @return Vector of colors corresponding to each class.
 */
std::vector<cv::Scalar> get_colors_for_classes(int num_classes);

/**
 * @brief Convert a cv::Mat image to a runtime_tensor.
 * @param ori_img Input image as a cv::Mat.
 * @param mode    Mode for tensor conversion ("CHW" or "HWC").
 * @return Runtime tensor containing the image data.
 */
runtime_tensor mat_to_tensor(cv::Mat &ori_img,std::string mode="CHW");

#endif