//-----------------------------------------------------------------------------

#include "Landmark_description.h"

#include <fstream>
#include <map>

//-----------------------------------------------------------------------------

//
// String to enum table
//
#if __APPLE__
const std::map<std::string, Landmark_description> LANDMARK_DESCRIPTION_TABLE = {
        { "RIGHT_EYE_OUTER", Landmark_description::RIGHT_EYE_OUTER, },
        { "RIGHT_EYE_UPPER", Landmark_description::RIGHT_EYE_UPPER, },
        { "RIGHT_EYE_INNER", Landmark_description::RIGHT_EYE_INNER, },
        { "RIGHT_EYE_LOWER", Landmark_description::RIGHT_EYE_LOWER, },
        { "NOSE_TIP",        Landmark_description::NOSE_TIP, },
        { "LEFT_EYE_OUTER",  Landmark_description::LEFT_EYE_OUTER, },
        { "LEFT_EYE_UPPER",  Landmark_description::LEFT_EYE_UPPER, },
        { "LEFT_EYE_INNER",  Landmark_description::LEFT_EYE_INNER, },
        { "LEFT_EYE_LOWER",  Landmark_description::LEFT_EYE_LOWER, },
        { "MOUTH_CORNER_LEFT",Landmark_description::MOUTH_CORNER_LEFT, },
        { "MOUTH_CORNER_RIGHT",Landmark_description::MOUTH_CORNER_RIGHT, },
        { "NECK",            Landmark_description::NECK, },
        { "RIGHT_HIP",       Landmark_description::RIGHT_HIP, },
        { "ROOT",            Landmark_description::ROOT, },
        { "LEFT_HIP",        Landmark_description::LEFT_HIP, },
        { "RIGHT_KNEE",      Landmark_description::RIGHT_KNEE, },
        { "LEFT_KNEE",       Landmark_description::LEFT_KNEE, },
        { "LEFT_EAR",        Landmark_description::LEFT_EAR, },
        { "LEFT_SHOULDER",   Landmark_description::LEFT_SHOULDER, },
        { "LEFT_ELBOW",      Landmark_description::LEFT_ELBOW, },
        { "LEFT_HAND",       Landmark_description::LEFT_HAND, },
        { "LEFT_ANKLE",      Landmark_description::LEFT_ANKLE, },
        { "RIGHT_EAR",       Landmark_description::RIGHT_EAR, },
        { "RIGHT_SHOULDER",  Landmark_description::RIGHT_SHOULDER, },
        { "RIGHT_ELBOW",     Landmark_description::RIGHT_ELBOW, },
        { "RIGHT_HAND",      Landmark_description::RIGHT_HAND, },
        { "RIGHT_ANKLE",     Landmark_description::RIGHT_ANKLE, },
};
#else
const std::map<std::string, Landmark_description> LANDMARK_DESCRIPTION_TABLE = {
    { "RIGHT_EAR_UPPER", Landmark_description::RIGHT_EAR_UPPER, },
    { "RIGHT_EAR_LOWER", Landmark_description::RIGHT_EAR_LOWER, },
    { "RIGHT_EYE_OUTER", Landmark_description::RIGHT_EYE_OUTER, },
    { "RIGHT_EYE_UPPER", Landmark_description::RIGHT_EYE_UPPER, },
    { "RIGHT_EYE_INNER", Landmark_description::RIGHT_EYE_INNER, },
    { "RIGHT_EYE_LOWER", Landmark_description::RIGHT_EYE_LOWER, },
    { "NOSE_TIP",        Landmark_description::NOSE_TIP, },
    { "LEFT_EYE_OUTER",  Landmark_description::LEFT_EYE_OUTER, },
    { "LEFT_EYE_UPPER",  Landmark_description::LEFT_EYE_UPPER, },
    { "LEFT_EYE_INNER",  Landmark_description::LEFT_EYE_INNER, },
    { "LEFT_EYE_LOWER",  Landmark_description::LEFT_EYE_LOWER, },
    { "LEFT_EAR_UPPER",  Landmark_description::LEFT_EAR_UPPER, },
    { "LEFT_EAR_LOWER",  Landmark_description::LEFT_EAR_LOWER, },
    { "MOUTH_LEFT",      Landmark_description::MOUTH_LEFT, },
    { "MOUTH_UPPER",     Landmark_description::MOUTH_UPPER, },
    { "MOUTH_RIGHT",     Landmark_description::MOUTH_RIGHT, },
    { "MOUTH_LOWER",     Landmark_description::MOUTH_LOWER, },
};
#endif

//-----------------------------------------------------------------------------

//
// Load landmark descriptions from file
//
bool
load_landmark_descriptions(const std::string& filename,
                           std::vector<Landmark_description>& landmark_descriptions)
{
    std::ifstream ifs(filename);

    if (!ifs)
    {
        printf("[ERROR] Cannot open %s for reading landmark description table\n",
               filename.c_str());
        return false;
    }

    landmark_descriptions.clear();

    std::string line;
    while (std::getline(ifs, line))
    {
        if (line.empty())
            continue;

        if (line.size() > 0 && line[0] == '#')
            continue;

        auto find_result = LANDMARK_DESCRIPTION_TABLE.find(line);
        if (find_result != LANDMARK_DESCRIPTION_TABLE.end())
        {
            landmark_descriptions.push_back(find_result->second);
        }
        else
        {
            landmark_descriptions.push_back(Landmark_description::UNKNOWN);
        }
    }

    ifs.close();

    return true;
}

//-----------------------------------------------------------------------------

//
// Get landmarks which are present in both sets a and b
//
bool
get_matching_landmarks(const std::vector<Landmark_description>& landmark_set_a,
                       const std::vector<Landmark_description>& landmark_set_b,
                       std::vector<Landmark_match>& matching_landmarks)
{
    for (size_t i = 0; i < landmark_set_a.size(); ++i)
    {
        Landmark_description a = landmark_set_a[i];

        if (a == Landmark_description::UNKNOWN)
            continue;

        for (size_t j = 0; j < landmark_set_b.size(); ++j)
        {
            Landmark_description b = landmark_set_b[j];

            if (a == b)
            {
                matching_landmarks.push_back({i, j});
            }
        }
    }

    return matching_landmarks.size() > 0;
}

//-----------------------------------------------------------------------------

