
#include "Facial_features_detection.h"
#include "Facial_features_detector_dlib.h"

#include "Landmark_mapping.h"

#include <float.h>


namespace graphene
{
namespace surface_mesh
{

Facial_features_detection::Facial_features_detection()
{
    detectors_.resize(FFD_MAX, nullptr);

    detectors_[FFD_DLIB] = new Facial_features_detector_dlib();
}

Facial_features_detection::~Facial_features_detection()
{

}

bool Facial_features_detection::load_model(const std::string &fn_model, FF_detectors type)
{
    if(! detectors_[type]->load_model(fn_model))
    {
        std::cout << "Facial_features_detection::load_model: [ERROR] Could not load model for "
                  << detectors_[type]->get_name() << " detector with filename \""
                  << fn_model << "\"." << std::endl;
        return false;
    }
    return true;
}


bool Facial_features_detection::detect_ff(const std::string& fn_image,
        FF_detectors type)
{
    Facial_features_detector* ffd = detectors_[type];
    if (ffd == nullptr)
    {
        std::cerr << "Facial_features_detection::detect_ff_and_map_to_pointset: [ERROR] No detector of type " << type << "." << std::endl;
        return false;
    }

    if (! ffd->detect(fn_image))
    {
        std::cerr << "Facial_features_detection::detect_ff_and_map_to_pointset: [ERROR] Unable to detect facial features." << std::endl;
        return false;
    }
    return true;

}

bool Facial_features_detection::map_ff_to_pointset(
        geometry::Point_set &pointset,
        const std::string &fn_image,
        const std::string &fn_cameras,
        FF_detectors type,
        const std::string& fn_landmark_validity)
{
    Facial_features_detector* ffd = detectors_[type];

    //load camera calibration
    utility::Agi_cameras cameras(fn_cameras);

    utility::Agi_camera *camera_of_image = cameras.get_camera_by_filename(fn_image);

    if (camera_of_image == nullptr)
    {
        std::cerr << "Facial_features_detection::map_ff_to_pointset: [ERROR] Unable to find camera for image with filename: \"" << fn_image << "\"." << std::endl;
        return false;
    }

    find_landmarks_swenninger(pointset, *camera_of_image, ffd->facial_features(), pointset.landmarks_, fn_landmark_validity);
//    find_landmarks_twaltema(pointset, *camera_of_image, ffd->facial_features(), pointset.landmarks_);

    //copy landmarks to selection for visualization
    pointset.selected_indices_ = pointset.landmarks_;

    return true;
}

bool Facial_features_detection::save_eye_features(const std::string &filename, FF_detectors type)
{
    Facial_features_detector* ffd = detectors_[type];
    if (ffd == nullptr)
    {
        std::cerr << "Facial_features_detection::save_eye_features: [ERROR] No detector of type " << type << "." << std::endl;
        return false;
    }

    return ffd->save_eye_features(filename);
}



}
}
