/**------------------------------------------------------------------------
 * @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: ViewSubsampler.h,v $
 *
 *
 *-----------------------------------------------------------------------*/

#ifndef __VIEW_SUBSAMPLER_H__
#define __VIEW_SUBSAMPLER_H__

#include <DAGDatabase.h> //for MatchInfo
#include <DAG.h>

using namespace dml;

class LockFile
{
	int fd; // lock file's descriptor
	String m_strFileName;
	bool m_bLocked; // 'true' if the lock creation was successful
	
public:
	LockFile() { m_bLocked = false; }
	virtual ~LockFile() { Unlock(); }
	
	bool Lock(const char* szLockFileName, unsigned int nSleepTime);
	void Unlock();
};

struct VIEWWEIGHT
{
	int nViewNumber;
	int nViewRankPos;
	double dVoteWeight;
	
	VIEWWEIGHT() { nViewNumber = nViewRankPos = 0; dVoteWeight = 0.0; }
};

struct OBJVIEWWEIGHT : public VIEWWEIGHT
{
	String strObjName;
	
	void Set(String objname, const VIEWWEIGHT& vw)
	{
		strObjName = objname;
		nViewNumber = vw.nViewNumber;
		nViewRankPos = vw.nViewRankPos;
		dVoteWeight = vw.dVoteWeight;
	}
};

typedef SmartArray<VIEWWEIGHT> VWArray;
typedef leda_d_array<leda_string, VWArray> ObjViewArray;

class ViewSubsampler
{
	struct Record
	{
		int nIndexedWithKBest;
		String strObjName;
		VWArray bmviews; //!< Badly matched views
		
		Record() { nIndexedWithKBest = 0; }
		Record(const Record& rhs) { operator=(rhs); }
		
		Record& operator=(const Record& rhs)
		{
			nIndexedWithKBest = rhs.nIndexedWithKBest;
			strObjName = rhs.strObjName;
			bmviews = rhs.bmviews;
			return *this;
		}
		
		std::istream& Read(std::istream& is)
		{
			is.read((char*)&nIndexedWithKBest, sizeof(nIndexedWithKBest));
			strObjName.Read(is);
			return bmviews.Read(is);
		}
		
		std::ostream& Write(std::ostream& os) const
		{
			os.write((char*)&nIndexedWithKBest, sizeof(nIndexedWithKBest));
			strObjName.Write(os);
			return bmviews.Write(os);
		}		
	};
	
	leda_list<Record> m_viewVotes;
	ObjViewArray m_rankedObjViews;
	
public:
	
    void AddViewWeights(int nViewsPerObject, const DAG* pQueryDag,
		const leda_array<MatchInfo>& matchList, const SmartArray<int>& neigViews, int kBest);
		
	void SaveViewWeights(const char* szDataFileName);

	bool RetrieveViewWeights(const char* szDataFileName, int nViewsPerObject, bool bRankByObject);
	
	VIEWWEIGHT GetViewRank(String strObjName, int nViewNumber) const
	{
		return m_rankedObjViews[(const char*)strObjName][nViewNumber - 1];
	}
	
	double CompVoteWeight(int nPos, int kBest) const;
	static SmartArray<int> RandomSubsampling(int nCurViewNum, int nNewViewNum);
};

#endif //__VIEW_SUBSAMPLER_H__

