//=============================================================================
#ifndef GRAPHENE_LANDMARKS_MANAGER_H
#define GRAPHENE_LANDMARKS_MANAGER_H
//=============================================================================

//== INCLUDES =================================================================


#include <string>
#include <vector>
#include <graphene/surface_mesh/data_structure/Surface_mesh.h>
#include <graphene/geometry/Point_set.h>

#include "Landmark_description.h"


//== NAMESPACE ================================================================


namespace graphene {
namespace surface_mesh {


using graphene::geometry::Point_set;


//== CLASS DEFINITION =========================================================


class Landmarks_manager
{
public: //---------------------------------------------------- public functions


    // constructor
    Landmarks_manager();

    bool load(Point_set* pointset, const std::string& filename);
    bool load(Surface_mesh* surface_mesh,
              const std::string& filename,
              const std::string& prop_name,
              const std::string& prop_lmvw);
    bool load_with_mapping(Surface_mesh* surface_mesh,
                           const std::string& filename,
                           const std::string& filename_mapping_fullbody_head,
                           const std::string& prop_name,
                           const std::string& prop_lmvw);

    bool load_landmark_descriptions(const std::string& filename,
                                    const std::string& prop_name,
                                    Surface_mesh* mesh);

    void save(const Point_set* pointset, const std::string& filename);
    void save(const Surface_mesh* surface_mesh,
              const std::string& filename,
              const std::string& prop_name);


    void clear();


    size_t n_landmarks_template(const Surface_mesh* template_mesh,
                                const std::string& prop_name);
    size_t n_landmarks_pointset(const Point_set* point_set) const;

    void get_landmarks_point_set_stdvec(const Point_set* point_set, std::vector<Point>& landm_ps)       const;
    void get_landmarks_template_stdvec(const Surface_mesh* template_mesh,
                                       std::vector<Point>& landm_tm,
                                       const std::string& prop_name) const;
    void get_landmarks_combined_stdvec(Surface_mesh* template_mesh, const Point_set* point_set,
                                       std::vector<Point>& landm_tm,
                                       std::vector<Point>& landm_ps,
                                       const std::string& prop_name,
                                       const std::string& prop_lmvw) const;

    void get_indices_pointset(const Point_set* point_set, std::vector<unsigned int>& indices) const;
    void get_indices_template(const Surface_mesh* template_mesh,
                              std::vector<Surface_mesh::Vertex>& indices,
                              const std::string& prop_name) const;

    void get_indices_template(const Surface_mesh* template_mesh,
                              std::vector<size_t>& indices,
                              const std::string& prop_name) const;

    bool get_matching_landmarks(Surface_mesh* mesh, std::vector<Landmark_match>& matching_landmarks);

    bool check_dimension(const Point_set* point_set,
                         const Surface_mesh* template_mesh,
                         const std::string& prop_name) const;

    bool read(const std::string& filename, std::vector<unsigned int>& indices);
    bool read(const std::string& filename, std::vector<unsigned int>& indices, std::vector<double>& local_weights);
    bool write(const std::string& filename, const std::vector<unsigned int>& indices);
    bool write_sel(const std::string& filename, const std::vector<unsigned int>& indices);

    void maybe_invalidate_landmarks(const std::string& fn_landmark_validity,
                                    Surface_mesh* template_mesh,
                                    Point_set* point_set,
                                    const std::string& prop_name,
                                    const std::string& description_prop_name = "");


private: //--------------------------------------------------- private functions

};


//=============================================================================
} // namespace surface_mesh
} // namespace graphene
//=============================================================================
#endif // GRAPHENE_LANDMARKS_MANAGER_H
//=============================================================================
