#include <gst/gst.h>

#include <fstream>
#include <iostream>

#include "config_manager.hpp"
// #include "gstnvdsinfer.h"
#include "gstnvdsmeta.h"
#include "nvds_version.h"
#include "nvdsinfer_custom_impl.h"
#include "custom_gstnvdsinfer.hpp"

class NvInferServerManager {
   private:
   public:
    struct Point2D {
        double x;  // X coordinate
        double y;  // Y coordinate

        // Constructor
        Point2D(double x_val = 0.0, double y_val = 0.0) : x(x_val), y(y_val) {}
    };
    GstElement *primary_detector = NULL;
    int pgie_batch_size;

    static unsigned int PGIE_NET_WIDTH;
    static unsigned int PGIE_NET_HEIGHT;
    static unsigned int MUXER_OUTPUT_WIDTH;
    static unsigned int MUXER_OUTPUT_HEIGHT;
    static unsigned int nvds_lib_major_version;
    static unsigned int nvds_lib_minor_version;
    static gint frame_number;
    static guint use_device_mem;
    std::string inferserver_pgie_config_file;
    static float threshold_body_detection;
    NvInferServerManager();
    bool create_nv_infer_server(int);
    ~NvInferServerManager();
    // static GstPadProbeReturn osd_sink_pad_buffer_probe(GstPad *,
    //                                                    GstPadProbeInfo *,
    //                                                    gpointer);
    //  void attach_probe_to_element(GstElement *);
    static GstPadProbeReturn pgie_pad_buffer_probe(GstPad *, GstPadProbeInfo *,
                                                   gpointer);
    //  static GstPadProbeReturn osd_sink_pad_buffer_probe_new(GstPad *,
    //                                                         GstPadProbeInfo
    //                                                         *, gpointer);
    static void *set_metadata_ptr(float *);
    static gpointer copy_user_meta(gpointer, gpointer);
    static void release_user_meta(gpointer, gpointer);
    static void update_frame_with_face_body_meta(uint, NvDsBatchMeta *, float *,
                                                 NvDsFrameMeta *);
    static uint extract_tensor_metadata(NvDsUserMeta *, NvDsInferNetworkInfo,
                                        NvDsBatchMeta *, NvDsFrameMeta *);
    static Point2D find_left_down_corner_shoulder(float *, uint);
};