/*
 * Copyright 2022 Google LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

// NMS (Non-Maximum Suppression) algorithm

#include "ssd_postprocess/nms.h"

#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#ifndef MIN
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
#endif
#ifndef MAX
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
#endif

// compute area of one box
static float compute_box_area(const BoxCornerEncode* box) {
  const float width = box->xmax - box->xmin;
  const float height = box->ymax - box->ymin;
  return MAX(0.0, width * height);
}

// compute IOU (intersection over union) of two boxes
static float compute_two_boxes_iou(const BoxCornerEncode* box1,
                                   const BoxCornerEncode* box2) {
  const float area1 = compute_box_area(box1);
  const float area2 = compute_box_area(box2);
  if (area1 <= 0 || area2 <= 0) return 0.0;

  BoxCornerEncode intersection_box = {.ymin = MAX(box1->ymin, box2->ymin),
                                      .xmin = MAX(box1->xmin, box2->xmin),
                                      .ymax = MIN(box1->ymax, box2->ymax),
                                      .xmax = MIN(box1->xmax, box2->xmax)};
  float intersection_area = compute_box_area(&intersection_box);
  return intersection_area / (area1 + area2 - intersection_area);
}

// comparator for qsort
static int comparator(const void* p, const void* q) {
  float x = ((BoxCornerEncode*)p)->score;
  float y = ((BoxCornerEncode*)q)->score;
  return (y > x) - (y < x);
}

// Perform non-maximum suppression algorithm to remove "similar" bounding boxes
void nms(Boxes* boxes_in, Boxes* boxes_out, const int max_boxes,
         const float iou_threshold) {
  int num_boxes = boxes_in->num_boxes;
  uint8_t* is_suppressed = (uint8_t*)malloc(num_boxes * sizeof(uint8_t));
  memset(is_suppressed, 0, num_boxes * sizeof(uint8_t));

  // quick sort from greatest to smallest
  qsort(boxes_in->box, num_boxes, sizeof(BoxCornerEncode), comparator);

  for (int i = 0; i < num_boxes; i++) {
    if (!is_suppressed[i]) {
      for (int j = i + 1; j < num_boxes; j++) {
        if (!is_suppressed[j]) {
          if (compute_two_boxes_iou(&(boxes_in->box[i]), &(boxes_in->box[j])) >
              iou_threshold) {
            is_suppressed[j] = 1;
          }
        }
      }
    }
  }

  int ind_out = 0;
  for (int i = 0; i < num_boxes; i++) {
    if (ind_out >= max_boxes) break;
    if (!is_suppressed[i]) {
      boxes_out->box[ind_out++] = boxes_in->box[i];
    }
  }
  boxes_out->num_boxes = ind_out;

  free(is_suppressed);
}
