#include "gstds_example_manager.hpp"

// #define NVDS_USER_OBJECT_META_LANDMARKS_AND_SOURCE_ID
// (nvds_get_user_meta_type("NVIDIA.NVINFER.USER_META"))
#define NVDS_USER_OBJECT_META_LANDMARKS_AND_SOURCE_ID \
    (nvds_get_user_meta_type(const_cast<gchar *>("NVIDIA.NVINFER.USER_META")))

#define MAX_DISPLAY_LEN 64
#define PGIE_CLASS_ID_PERSON 0

gint GstdsExampleManager::frame_number = 0;

GstdsExampleManager::GstdsExampleManager() {}

bool GstdsExampleManager::create_gstds_example() {
    custom_plugin = gst_element_factory_make("dsexample", "nvdsgst_dsexample");
    g_object_set(G_OBJECT(custom_plugin), "full-frame", 0, NULL);
    if (!custom_plugin) {
        g_printerr("Custom_plugin could not be created. Exiting.\n");
        return false;
    }
    return true;
}

// Attach probe to a pad in the pipeline
void GstdsExampleManager::attach_probe_to_element() {
    GstPad *src_pad = gst_element_get_static_pad(custom_plugin, "src");
    if (!src_pad) {
        std::cerr << "Unable to get gst ds example src pad\n";
        return;
    }

    gst_pad_add_probe(src_pad, GST_PAD_PROBE_TYPE_BUFFER,
                      gstds_example_src_pad_buffer_probe, NULL, NULL);
    gst_object_unref(src_pad);
}

/* This is the buffer probe function that we have registered on the src pad
 * of the gstds_example element. All the infer elements in the pipeline shall
 * attach their metadata to the GstBuffer, here we will iterate & process the
 * metadata forex: class ids to strings, counting of class_id objects etc. */
GstPadProbeReturn GstdsExampleManager::gstds_example_src_pad_buffer_probe(
    GstPad *pad, GstPadProbeInfo *info, gpointer u_data) {
    (void)pad;
    (void)u_data;
    GstBuffer *buf = (GstBuffer *)info->data;
    guint num_rects = 0;
    guint person_count = 0;
    NvDsObjectMeta *obj_meta = NULL;
    NvDsMetaList *l_frame = NULL;
    NvDsMetaList *l_obj = NULL;
    NvDsDisplayMeta *display_meta = NULL;

    NvDsBatchMeta *batch_meta = gst_buffer_get_nvds_batch_meta(buf);

    for (l_frame = batch_meta->frame_meta_list; l_frame != NULL;
         l_frame = l_frame->next) {
        NvDsFrameMeta *frame_meta = (NvDsFrameMeta *)(l_frame->data);
        int offset = 0;
        for (l_obj = frame_meta->obj_meta_list; l_obj != NULL;
             l_obj = l_obj->next) {
            obj_meta = (NvDsObjectMeta *)(l_obj->data);
            if (obj_meta->class_id == PGIE_CLASS_ID_PERSON) {
                person_count++;
                num_rects++;
                // std::cout << "In GstdsExample src "
                //           << "x = " << obj_meta->rect_params.left
                //           << " y = " << obj_meta->rect_params.top
                //           << " w = " << obj_meta->rect_params.width
                //           << " h = " << obj_meta->rect_params.height
                //           << " score = " << obj_meta->confidence
                //           << "  Object ID: " << obj_meta->object_id
                //           << std::endl;
            }

            NvDsUserMeta *user_meta = NULL;
            NvDsMetaList *l_user_meta = NULL;
            float *user_meta_data = NULL;
            for (l_user_meta = obj_meta->obj_user_meta_list;
                 l_user_meta != NULL; l_user_meta = l_user_meta->next) {
                user_meta = (NvDsUserMeta *)(l_user_meta->data);
                user_meta_data = (float *)user_meta->user_meta_data;

                // user_meta->base_meta.meta_type == 7 means it is user-defined
                // metadata (NVDS_USER_META).

                // This is typically used when you attach custom metadata
                // (like your float* user_meta_data) to an object
                // (NvDsObjectMeta) using DeepStream APIs.

                (void)user_meta_data;
                if (user_meta->base_meta.meta_type ==
                    NVDS_USER_OBJECT_META_LANDMARKS_AND_SOURCE_ID) {
                    // std::cout << "In GstdsExample src "<<std::endl;
                    // for (int jkl = 0; jkl < 57; jkl++)
                    //     std::cout << user_meta_data[jkl] << std::endl;
                }
            }
        }
        display_meta = nvds_acquire_display_meta_from_pool(batch_meta);
        NvOSD_TextParams *txt_params = &display_meta->text_params[0];
        display_meta->num_labels = 1;
        txt_params->display_text = (gchar *)g_malloc0(MAX_DISPLAY_LEN);
        offset = snprintf(txt_params->display_text, MAX_DISPLAY_LEN,
                          "Person = %d ", person_count);
        (void)offset;

        nvds_add_display_meta_to_frame(frame_meta, display_meta);
    }
    // g_print(
    //     "In GstdsExample src "
    //     "Frame Number = %d "
    //     "Person Count = %d\n",
    //     frame_number, person_count);

    frame_number++;
    return GST_PAD_PROBE_OK;
}
