#include "face_candid_trace.hpp"

FaceCandidTrace::FaceCandidTrace() {
    maxlen = 150;
    // interval_frame_log=20;
    face_detection_threshold = 0.5;
    face_surface_threshold = 100;
    termostat_threshold = 0.00001;
}

bool FaceCandidTrace::filter(FaceCandidate* face_candidate) {
    float w = face_candidate->w;
    float h = face_candidate->h;
    float face_surface = w * h;
    float score_face = face_candidate->face_score;  // result["temp_face_score"]
    // int frame = face_candidate->frame_number; //result["frame_count"]

    if (score_face < face_detection_threshold ||
        face_surface < face_surface_threshold) {
        // if self.logger and self._should_log(frame):
        //     self.logger.info(f"Ignore instance — surface={face_surface},
        //     score={score:.2f}, track_id={result['track_id']} @ {frame}",
        //     extra={"stream_id": stream_id})
        // elif self._should_log(frame):
        //     print(f"Ignore instance — surface={face_surface},
        //     score={score:.2f}, track_id={result['track_id']} @ {frame}")
        return false;
    }
    return true;
}

float FaceCandidTrace::metric(FaceCandidate* face_candidate) {
    // x1, y1, x2, y2 = result["face_bbox"]
    // face_surface = (y2 - y1) * (x2 - x1)
    float w = face_candidate->w;
    float h = face_candidate->h;
    float face_surface = w * h;
    face_surface = std::max<float>(face_surface, 30000);
    face_surface = face_surface / 30000;
    float out = 0.3 * face_candidate->face_score + 0.7 * face_surface;
    // # self.termostat_threshold = 0.02 * out
    return out;
}

float FaceCandidTrace::check_existence(int object_id, int source_id) {
    for (std::vector<FaceBody>::iterator iter = queue.begin();
         iter != queue.end(); iter++) {
        if (((*iter).object_id == object_id) &&
            ((*iter).source_id == source_id)) {
            return (*iter).face_score;
        }
    }
    return 0;
}

bool FaceCandidTrace::add(FaceCandidate* face_candidate) {
    if (filter(face_candidate)) {
        float current_metric = metric(face_candidate);
        float prev = check_existence(face_candidate->object_id,
                                     face_candidate->source_id);
        // prev = self.queue.get(track_id, 0)
        if ((current_metric - termostat_threshold) > prev) {
            queue.emplace_back(
                FaceBody{face_candidate->object_id, face_candidate->source_id,
                         face_candidate->frame_number, current_metric});
            std::cout << "FaceCandidTrace source_id = "
                      << face_candidate->source_id
                      << " frame_num = " << face_candidate->frame_number
                      << " object_id = " << face_candidate->object_id
                      << " size queue = " << queue.size() << std::endl;
            // self.queue.add(track_id, current_metric);
            return true;
        }
        // int frame_count = face_candidate->frame_number;
        // //result["frame_count"] if self.ogger and
        // self._should_log(frame_count):
        //     self.logger.info(f"Ignore (better seen before):
        //     now={current_metric - self.termostat_threshold:.2f},
        //     history={prev:.2f}, track_id={result['track_id']} @
        //     {frame_count}", extra={"stream_id": stream_id})
        // elif self._should_log(frame_count):
        //     print(f"Ignore (better seen before): now={current_metric -
        //     self.termostat_threshold:.2f}, history={prev:.2f},
        //     track_id={result['track_id']} @ {frame_count}")
    }
    return false;
}