/**------------------------------------------------------------------------
 * @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
 * 
 * $Log: Stats.h,v $
 *
 *-----------------------------------------------------------------------*/
#ifndef __STATS_H__
#define __STATS_H__

#include <DAGDatabase.h>
#include <DAG.h>
#include <BasicUtils.h>
 
// NOT_SET is a big negative number that is easy to spot when computing stats
#define NOT_SET -100

#define	MAXPOS 10000
#define	MAXVIEW 128

using namespace dml;

class STATINFO
{
public:
	bool bCompViewStats;
    leda_array<MatchInfo> matchList;
    int nParamsToSet;

	class INFOVAR
	{
		int nDAGId;					//<! ID of the dag.
		double dSimilarity;	        //<! Assigned indexing or matching similarity
		
		int nBestRankingPosition;   //<! Best position in either the indexing or matching ranking
		int nWorstRankingPosition;  //<! Worst position in either the indexing or matching ranking

		int nBestIdxPos;      		//<! Best position in the index (only if appropiate)
		int nWorstIdxPos;     		//<! Worst position in the index (only if appropiate)

	public:
		INFOVAR() { Clear(); }
		void Clear();
		int GetDAGId() const { return nDAGId; }

		void SetRankPos(int currentRankPos, const leda_array<MatchInfo>& rankList);
		void SetRankPos(int currentRankPos, const leda_array<MatchInfo>& rankList, const INFOVAR& queryPos);
		void SetIdxPos(int currentIdxPos, const leda_array<MatchInfo>& idxRankList);
		void SetIdxPos(int currentIdxPos, const leda_array<MatchInfo>& idxRankList, const INFOVAR& queryPos);

		bool IsNotSet() const;

		static int GetBestPos(int i, const leda_array<MatchInfo>& matches);
		static int GetWorstPos(int i, const leda_array<MatchInfo>& matches);

		friend std::ostream& operator<<(std::ostream &os, const INFOVAR& v);
	};

    INFOVAR queryObj;	//<! query object
    INFOVAR rightClass; //<! first object of the same class than the query object
    INFOVAR wrongClass; //<! first object of a different class than the query object
    INFOVAR neigType1;  //<! type-3 closest neig. in the viewing sphere
    INFOVAR neigType2;  //<! type-9 closest neig. (including the type-3 closest neigbours)
    INFOVAR topRanked;  //<! info of the first ranked DAG, whatever the DAG is.

	STATINFO() { bCompViewStats = false; }
	void InitStats();

	/*!
		@brief Return number of parameters (INFOVAR's) that need to be set
	*/
	int GetParamCount() const { return nParamsToSet; }

	void ComputeStats(const DAG* pQueryDag);
	void ComputeCrossRankingIdxStats(const STATINFO& matStats);
	int FindDAGPos(const DAG* pQueryDag) const;
	int FindDAGPos(int nDAGId) const;

	static void WriteHeader(std::ostream& os, int nFileIdx, int nIdxKBest, double dMaxOcclusionRate);
	static void Write(std::ostream& os, int i, int nViewNum, const STATINFO& idxSt, const STATINFO& matSt,
		double dCompTime, double dOcclusionRate);
	static void WriteTailer(std::ostream& os);

	friend std::ostream& operator<<(std::ostream& os, const STATINFO& v);
};

bool GetClosestViews(int i, int res, int& a, int &b, int &c);
bool GetClosestViews2(int i, int res, SmartArray<int>& neigs, bool bIncludeFirstLevel);
SmartArray<int> GetClosestViewsByRange(int i, int res, const double& range);
SmartArray<int> GetSymmetricViewMap();

#endif //__STATS_H__
