/**------------------------------------------------------------------------
 * @file
 *
 * Copyright 2001 by the University of Toronto (UT).
 *
 *                       All Rights Reserved
 * 
 * Permission to copy and modify this software and its documentation 
 * only for internal use in your organization is hereby granted, 
 * provided that this notice is retained thereon and on all copies.  
 * UT makes no representations as to the suitability and operability 
 * of this software for any purpose.  It is provided "as is" without 
 * express or implied warranty.
 *
 * UT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 * ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT
 * SHALL UT BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL
 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA
 * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
 * PERFORMANCE OF THIS SOFTWARE.
 *
 * No other rights, including for example, the right to redistribute 
 * this software and its documentation or the right to prepare 
 * derivative works, are granted unless specifically provided in a 
 * separate license agreement.
 *
 * Author: Diego Macrini
 *
 *-----------------------------------------------------------------------*/
#ifndef __DAG_MEMORY_DB_SET_H__
#define __DAG_MEMORY_DB_SET_H__

#include <vector>
#include <map>
#include <string>
#include <BasicTypedefs.h>

namespace dml {

typedef std::vector<DAGPtr> DAGParses;
typedef std::vector<bool> BoolArray;
typedef std::vector<BoolArray> DBPresence;
typedef std::map<std::string, std::vector<int> > ClassMap;

/*!
	A memory database set is an array of arrays organizied
	such that each "row" correspondes to the same DAG ID
	on several databases.
*/
class DAGMemoryDBSet : protected std::vector<DAGParses>
{
	DAGDatabase* m_dbs;
	DBPresence m_dbDagPresence;
	ClassMap m_classMap;

public:
	DAGMemoryDBSet()
	{
		m_dbs = NULL;
	}

	~DAGMemoryDBSet()
	{
		delete[] m_dbs;
	}

	DAGDatabase* GetDatabase(int i) const
	{
		return &m_dbs[i];
	}

	/*! 
		Creates a square matrix that identifies which DAGs are in
		the DB as a function of each possible query DAG (row index)
	*/
	void InitDBDagPresence()
	{
		const unsigned int N = size();

		m_dbDagPresence.resize(N);

		// Make sure that each row is of the righ size
		// and the initialize it to true (resize init only works
		// if a resize is neede, so init must be done explicitly).
		for (unsigned int i = 0; i < N; i++)
		{
			m_dbDagPresence[i].clear(); //force resize
			m_dbDagPresence[i].resize(N, true);
		}
	}

	bool SetDBDagPresence(int experimentId, int step, int param);

	void SetClassMap();

	int FindExemplarIndex(const char* className, int exemplarId)
	{
		std::vector<int>& inds = m_classMap[className];

		for (unsigned int i = 0; i < inds.size(); i++)
			if (inds[i] == exemplarId)
				return (int)i;

		return -1;
	}

	bool IsDAGPresent(unsigned int i, unsigned int j) const
	{
		return m_dbDagPresence[i][j];
	}

	unsigned int CountNotPresent(unsigned int i) const
	{
		const unsigned int sz = m_dbDagPresence[i].size();
		unsigned int count = 0;

		for (unsigned int j = 0; j < sz; j++)
			if (!m_dbDagPresence[i][j])
				count++;

		return count;
	}

	bool LoadDAGs(const char* szPrefix, int from, int to);

	unsigned int ParseCount() const
	{
		return (empty()) ? 0 : front().size();
	}

	unsigned int DAGCount() const
	{
		return size();
	}

	const DAGParses& GetParses(unsigned int i) const
	{
		return (*this)[i];
	}

	DAGParses& GetParses(unsigned int i)
	{
		return (*this)[i];
	}

	String GetDAGLabel(unsigned int i) const
	{
		return GetParses(i).front()->GetDAGLbl();
	}

	const DAG* GetDAG(unsigned int i) const
	{
		return operator[](i).front();
	}
};

}

#endif //__DAG_MEMORY_DB_SET_H__
