#ifndef	_DATASET_H
#define	_DATASET_H

#include <string>
#include <vector>
#include <map>

using namespace std;

// map of words/terms/authors/conferences [string => int]
typedef map<string, int> mapstr2id;
// map of words/terms/authors/conferences [int => string]
typedef map<int, string> mapid2str;

class document {
public:
	int *words;
	int *authors; 
    int nwords;	// number of word tokens in a document
	int nauthors; // number of authors in a document
	double timestamp; // timestamp for a document
    
    document() {
		this->words = NULL; 
		this->authors = NULL; 

		this->nwords = 0; 
		this->nauthors = 0; 

		this->timestamp = 0.0; 
    }
    
    document(int nwords, int nauthors, double timestamp) {
		this->nwords = nwords; 
		this->words = new int [nwords]; 

		this->nauthors = nauthors; 
		this->authors = new int [nauthors]; 

		this->timestamp = timestamp; 
    }
    
    document(int nwords, int *words, int nauthors, int *authors, double timestamp) {
		this->nwords = nwords;
		this->words = new int[nwords]; 
		memcpy(this->words, words, nwords * sizeof(int)); 

		this->nauthors = nauthors; 
		this->authors = new int[nauthors]; 
		memcpy(this->authors, authors, nauthors * sizeof(int)); 

		this->timestamp = timestamp; 
    }
    
    document(vector<int> &words, vector<int> &authors, double timestamp) {
		this->nwords = words.size();
		this->words = new int[this->nwords];
		for (int i = 0; i < this->nwords; i++) {
			this->words[i] = words[i];
		}

		this->nauthors = authors.size(); 
		this->authors = new int[this->nauthors]; 
		for (i = 0; i < this->nauthors; i++) {
			this->authors[i] = authors[i]; 
		}

		this->timestamp = timestamp; 
    }
    
    ~document() {
		if (words != NULL) {
			delete words;
		}

		if (authors != NULL) {
			delete authors; 
		}
    }
};

class dataset {
public:
    document **docs; 
    int M; // number of documents
    int V; // number of unique words
	int A; // number of unique authors
    
    dataset() {
		this->docs = NULL; 
		this->M = 0; 
		this->V = 0; 
		this->A = 0; 
    }
    
    dataset(int M) {
		this->M = M; 
		this->V = 0; 
		this->A = 0; 
		this->docs = new document * [M]; 
    }   
    
    ~dataset() {
		if (docs != NULL) {
			for (int i = 0; i < M; i++) {
				delete docs[i];
			}
		}
		delete docs;
    }
    
    void deallocate() {
		if (docs != NULL) {
			for (int i = 0; i < M; i++) {
				delete docs[i];
			}
		}
		delete docs;
		docs = NULL;
    }
    
    void add_doc(document *doc, int idx) {
		if (0 <= idx && idx < M) {
			docs[idx] = doc;
		}
    } 

    static int write_wordmap(string wordmapfile, mapstr2id *pword2id); 
	static int write_authormap(string authormapfile, mapstr2id *pauthor2id); 
    static int read_wordmap(string wordmapfile, mapstr2id *pword2id); 
    static int read_wordmap(string wordmapfile, mapid2str *pid2word); 
	static int read_authormap(string authormapfile, mapstr2id *pauthor2id); 
	static int read_authormap(string authormapfile, mapid2str *pid2author); 
    
    int read_trndata(string dfile, string wordmapfile, string authormapfile); 
};

#endif