/**------------------------------------------------------------------------
 * @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: Maxim Trokhimtchouk (trokhim@cs.utoronto.ca)
 *
 * $Log: matchingsystem.hpp,v $
 * Revision 1.1.1.1  2002/03/10 07:38:07  dmac
 * Imported sources
 *
 * Revision 1.1  2001/10/03 20:19:57  dmac
 * Added file
 *
 *
 *-----------------------------------------------------------------------*/

#ifndef __MATCHINGSYSTEM_HPP__
#define __MATCHINGSYSTEM_HPP__

#include <vector>
#include <stack>
#include <map>
#include <string>
#include <iostream>

#include <LEDA/string.h>
#include <LEDA/queue.h>
#include <LEDA/list.h>
#include <LEDA/graph_alg.h>
#include <LEDA/d_array.h>
#include <LEDA/tuple.h>

#include "memorydatabase.hpp"
#include "diskdatabase.hpp"
#include "matchingdatabase.hpp"

///DAGMatchingdatabase class manages all of the databases require for matching as one
///object.

template <class DAG>
class DAGMatchingDatabase
{
public:
	///instance of the prototypes database.
	MemoryDatabase<DAGPrototype> prototypes;
	///instance of the views database.
	MemoryDatabase<DAGView> views;
	///instance of the regions database.
	MemoryDatabase<DAGRegion> regions;
	///instance of the types database.
	DAGTypeDatabase< MemoryDatabase<DAGType> > types;
	///instance of the DAGs database.
	MemoryDatabase<DAG> DAGs;
	///instance of the near neighbour search database.
	DAGSearchDatabase index;
	
public:
	///Does nothing. User must open each database independently.
	DAGMatchingDatabase();
	///Destructor.
	~DAGMatchingDatabase();
	
	///Writes configuration of each individual database to a file with 'filename'.
	bool Write(string& filename);
	///Reads configuration of each individual database from a file.
	bool Read(string& filename);	
};

//Structure that contains match info
template <class DAG>
class MatchData
{
public:
	typename DAG::distance_type distance;
	ID prototype;

	MatchData();
	MatchData(ID prot, typename DAG::distance_type dist);
	friend bool operator< <>(const MatchData<DAG>& a, const MatchData<DAG>& b);
};


template <class T>
bool operator< (const MatchData<T>& a, const MatchData<T>& b)
{
	typename DAG::distance_type ap;
	typename DAG::distance_type bp;

	ap = a.distance;
	bp = b.distance;

	if(ap < bp)
		return true;
	else
		return false;
}


///Class used for matching DAGs
/**
*DAGMatcher implements high level interface for matching and indexing, as well as,
*for updating of the matching system. A parameter for this class is a DAGMatchingDatabase
*class instance, which manages the access to the data used by DAG matcher. 
*This instance must be instanciated by the user independently. This is done to give user
*option to perform custom configuration of the DAG matching database.
*/
template <class DAG>
class DAGMatcher
{
	///Reference to an instance of DAGMatchingDatabase class
	DAGMatchingDatabase<DAG>& data;

public:
	/**
	*Constructor.
	*@param mdata is a reference to an instance of DAG matching database
	*/
	DAGMatcher(DAGMatchingDatabase<DAG>& mdata);

	///Destructor.
	virtual ~DAGMatcher();
	
	///GetSimilar function
	/**
	*This function returns k closest prototypes found in the near 
	*neighbour search database.
	*@param dag is an reference to a test DAG.
	*@param m_list is a reference to a vector that contains at most 
	*@param m)list k closest prototypes found.
	*@param k is the maximum number of closest prototypes returned. 
	*@param k if number of returned prototypes is less then initial k, k is modified.
	*/
	void GetSimilar(DAG& dag, vector< MatchData<DAG> >& m_list, int& k);
	///SortByClosest function
	/**
	*This function sorts prototypes refered to in m_list by their similarity to dag,
	*most similar prototypes are first.
	*@param dag is a reference to a test DAG
	*@param m_list is a reference to a vector that contains closest prototypes found.
	*/
	void SortByClosest(DAG& dag, vector< MatchData<DAG> >& m_list);

	///GetMatch function
	/**
	*Function that retrives a vector of the most likely matches for a DAG.
	*@param dag is a test DAG.
	*@param k is the number of the most likely dags to be returned.
	*@return Returns a vector of the most likely matches.
	*NOTE: FUNCTION AS OF YET IS NOT IMPLEMENTED
	*/
	vector< MatchData<DAG> > GetMatch(DAG& dag, int k = 3);
 
	///Implements necessary improvements to the database in the case the actual 
	///type of the test DAG is known.
	///NOTE: NOT IMPLEMENTED.
	void Update(ID id = NULLID);
};

#include "matchingsystem.hxx"

#endif  //__MATCHINGSYSTEM_HPP__
