#pragma once
#ifndef DATASET_H_
#define DATASET_H_

#include <string>
#include <map>
#include <set>
#include "abc.h"


using std::string;
using std::map;
using std::set;

struct Sample : public XmlSerializableABC {
    const static string xml_root_name;
    const static string xml_label_name;
    const static string xml_path_name;
    const static string xml_data_name;

    string label; //class
    string path;  //path to wim, loop data and image
    vector<data_t> data;

    TCXMLnode* to_node(void) const;
    Sample& from_node(TCXMLnode* node);
};


struct ClassLabel : public XmlSerializableABC {
    const static string xml_root_name;
    const static string xml_name_name;
    const static string xml_code_name;
    const static string xml_enabled_name;

    string name;  //name of class, for example "car"
    label_t code;
    bool enabled;
    size_t count = 0;

    TCXMLnode* to_node(void) const;
    ClassLabel& from_node(TCXMLnode* node);

};

class MetaData : public XmlSerializableABC {
    friend class Dataset;

    map<string, ClassLabel> _classes; //key - class name
    vector<string> _features;

    MetaData() {};
protected:
    //const vector<string>& features() const { return _features; }
    //const vector<ClassLabel>& classes() const {return _classes;}

    bool add_class(const ClassLabel& cl);
    bool remove_class(const string& name);
    bool class_exists(const string& name) const;
    const map<string, ClassLabel>& classes() const { return _classes; }
    const set<label_t> get_enabled_class_codes() const;
    const set<string> get_classes(label_t class_code) const;

    TCXMLnode* to_node(void) const;
    MetaData& from_node(TCXMLnode* node);
public:
    const static string xml_root_name;
    const static string xml_features_name;
    const static string xml_classes_name;
};


class Dataset : public XmlSerializableABC {
    MetaData _meta;
    map<string, Sample> _samples; //key - sample path

public:
    const static string xml_root_name;
    const static string xml_samples_name;
    Dataset() {}
    Dataset(const std::string& filename);

    const ClassLabel& get_class_label(string label) const;
    const std::pair<Matrix<data_t>, vector<label_t> > samples_to_Xy(const vector<Sample>& samples) const;

    bool add_sample(const Sample& s);
    bool remove_sample(const string& path);

    const set<label_t> get_enabled_class_codes() const;
    const set<string> get_classes(label_t class_code) const;
    const vector<Sample> get_enabled_samples() const;

    TCXMLnode* to_node(void) const;
    Dataset& from_node(TCXMLnode* node);

	string info() const;

};



#endif 