/*
    Copyright (C) 2012 Bartosz Broda, Jacek Bochenek, Łukasz Biłeńkij, 
    Damian Jaworski, Wojciech Mazur, Dominik Piasecki, Maciej Piasecki, 
    Radosław Ramocki
    
    This program is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by the Free
Software Foundation; either version 3 of the License, or (at your option)
any later version.

    This program is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. 

    See the LICENSE and COPYING files for more details.
*/

#ifndef MATRICES_SIMMATRIX_H
#define MATRICES_SIMMATRIX_H

#include "matrices_headers.h"
#include "Matrix.h"
#include "Feature.h"

namespace Matrices
{
	/**
	 * Class for operation on symmetric similarity matrix. Only stores values below and on the diagonal and automatically converts
	 * calls to cells above the diagonal to corresponding cells below diagonal.
	 */
	class MATRICES_API SymmetricSimMatrix : public Matrix
	{
	public:
		/// Standard cmatrix -tor
		SymmetricSimMatrix(const std::string &name, size_t rows);
		virtual ~SymmetricSimMatrix(void);
		/**
		  * Retrieves a copy column. Column is dynamically allocated every time, so for large matrices calls to this method
		  * can seriously affect performance. Memory should be freed by calling Matrix::FreeMem.
		  */
		virtual double* GetColumn(size_t colNo);
		/**
		  * Retrieves a copy of a row. Row is dynamically allocated every time, so for large matrices calls to this method
		  * can seriously affect performance. Memory should be freed by calling Matrix::FreeMem.
		  */
		virtual double* GetRow(size_t rowNo);
		/**
		 * Calls GetRow(rowNo)
		 **/
		virtual double* operator[](size_t rowNo);
		/// Acts as described in base class
		virtual void SetRow(std::vector<double> &row, size_t rowIndex);
		/// Acts as described in base class
		virtual void SetRow(double* row, size_t rowIndex);
		/// Acts as described in base class
		virtual void SetColumn(double* col, size_t colIndex);
		/// Acts as described in base class
		virtual void SumRows(double *row, size_t rowIndex);
		/**
		 * This operation does not make sense for this type of matrix. Always throws std::runtime_error.
		*/
		virtual Matrix*& Transpose(Matrix*&  returnMatrix);
		/** 
		 * Acts as described in base class, the only difference is automatic conversion of calls to cells over diagonal
		 * to below the diagonal
		 */ 
		virtual void SetCell(double val, size_t rowInd, size_t colInd);
		/** 
		 * Acts as described in base class, the only difference is automatic conversion of calls to cells over diagonal
		 * to below the diagonal
		 */ 
		virtual double GetCell(size_t rowInd, size_t colInd);
		/// Acts as described in base class
		virtual void Clear();
		/** 
		 * Acts as described in base class, the only difference is automatic conversion of calls to cells over diagonal
		 * to below the diagonal
		 */ 
		virtual void AddToCell(double value, size_t rowIndex, size_t columnIndex);
		/// Acts as described in base class
		virtual void Clone(Matrix* matrix);
		/// Clones matrix into another SymmetricSimMatrix (the matrix has to be created)
		virtual void SetDescriptor(const std::string &name, size_t rows, size_t columns);
		/**
		 * Sets LabelIndex class for objects (e.g., lemmas) described by this similarity matrix.
		 */ 
		void SetLabelIndex(const LabelIndex &label_index);
		/**
		 * Retrieves similarity between objects described by this matrix identified by "names" (std::strings, e.g.,
		 * lemmas).
		 * \return Similarity between two objects or 0 if any of the objects was not found in th matrix.
		 * \note Will not act properly if labels were not set.
		 * \see SetLabelIndex
		 */ 
		double GetSimilarity(const std::string& w1, const std::string w2);

	private:
		/// Row map - indices of columns points to values
		typedef std::map<size_t, double> RowMap;
		/// matrix type
		typedef std::vector<RowMap> Rows;
		/// rows of a matrix
		Rows m_vRows;
		/// labels of objects described by matrix
		LabelIndex m_LabelIndex;
	};

	/// Shared pointer to SymmetricSimMatrix
	typedef boost::shared_ptr<SymmetricSimMatrix> SymmetricSimMatrixPtr;
}//Matrices

#endif //MATRICES_SIMMATRIX_H

