/*---------------------------------------------------------------
	FILE: CFeature.h

   Part of the MRPT Library
   ISA - Universidad de Malaga - http://www.isa.uma.es

   Autor: Antonio J. Ortiz de Galisteo (AJOGD)
  ---------------------------------------------------------------*/
#ifndef CFeature_H
#define CFeature_H

#include <MRPT/UTILS/utils_defs.h>
#include <MRPT/UTILS/CMRPTImage.h>

namespace UTILS
{
	/** CFeature class is a structure for control and storage of features information
	 */
	class CFeature
	{
	protected:
        struct feat{
            int				name;	//inicialmente es el indice pero si se eliminan caract. sera distinto
			int				hits;	//aciertos de matching, utilizados para borrar caracteristicas
			CMRPTImage		patch;
		};
		std::vector<feat> feat_vector;
	public:
/********************************************************************************************************************/
		/**	Constructor with a patch
		 */
		CFeature(const int &n,const int &h,const CMRPTImage &p)
		{
			ASSERT_((p.getWidth()==21) & (p.getHeight()==21));
			feat_vector.resize(1);
			feat_vector[0].name=n;
			feat_vector[0].hits=h;
			feat_vector[0].patch=p;
		}
		/**	Constructor without a patch
		 */
		CFeature(const int &n,const int &h)
		{
			feat_vector.resize(1);
			feat_vector[0].name=n;
			feat_vector[0].hits=h;
		}

		/**Default constructor
		 */
		CFeature()
		{
			feat_vector.resize(0);
		}
/********************************************************************************************************************/
		/**Return the numerical name of the feature
		 */
		int  get_name(const size_t &index)
		{
			if (index>=size())
				THROW_EXCEPTION("Index out of bounds in CFeature::get_name");
			return feat_vector[index].name;
		}

		/**Set the numerical name of the feature in the integer variable 'n'
		 */
		void  get_name(const size_t &index,int &n)
		{
			if (index>=size())
				THROW_EXCEPTION("Index out of bounds in CFeature::get_name");
			n=feat_vector[index].name;
		}

		/**Return the number of hits. The hits is the score of matching right.
		 */
		int  get_hits(const size_t &index)
		{
			if (index>=size())
				THROW_EXCEPTION("Index out of bounds in CFeature::get_hits");
			return feat_vector[index].hits;
		}

		/**Set the number of hits into the integer variable h. The hits is the score of matching right.
		 */
		void  get_hits(const size_t &index,int &h)
		{
			if (index>=size())
				THROW_EXCEPTION("Index out of bounds in CFeature::get_hits");
			h=feat_vector[index].hits;
		}

		/**Read the image which represents the feature
		 */
		void  get_patch(const size_t &index,CMRPTImage &im)
		{
			if (index>=size())
				THROW_EXCEPTION("Index out of bounds in CFeature::get_patch");
			im=feat_vector[index].patch;
		}

		/**Set the numerical name of the feature
		 */
		void  set_name(const size_t &index,const int &n)
		{
			if (index>=size())
				THROW_EXCEPTION("Index out of bounds in CFeature::set_name");
			feat_vector[index].name=n;
		}

		/**Set the number right matches of the feature
		 */
		void  set_hits(const size_t &index,const int &h)
		{
			if (index>=size())
				THROW_EXCEPTION("Index out of bounds in CFeature::set_hits");
			feat_vector[index].hits=h;
		}

		/** Write the patch (21x21 pixels) which represents the features, extracting 10 pixeles round to
		 *  (row,col) position on the image
		 */
		void  set_patch(const size_t &index,const unsigned int col, const unsigned int row, CMRPTImage &img)
		{
			if (index>=size())
				THROW_EXCEPTION("Index out of bounds in CFeature::set_patch");
			if ((col<10) | (col>img.getWidth()-11) | (row<10) | (row>img.getHeight()-11) | (index >= feat_vector.size()))
			{
				std::cout<<"index: "<<index<<"\n";
				std::cout<<"row: "<<row<<"\n";
				std::cout<<"col: "<<col<<"\n";
				THROW_EXCEPTION("Error while setting patch in CFeature::set_patch. Try to set patch out of image bounds");
			}
			img.extract_patch(feat_vector[index].patch,col-10,row-10,21,21);
		}

		/** Takes the image 'p' as the patch of the feature
		 */
		void  set_patch(const size_t &index,const CMRPTImage &p)
		{
			if (index>=size())
				THROW_EXCEPTION("Index out of bounds in CFeature::set_patch");
			if (index >= feat_vector.size())
				THROW_EXCEPTION("Error while setting patch, index out of range");
			feat_vector[index].patch = p;
		}

		/** Returns the number of features stored
		 */
		size_t  size(){return feat_vector.size();}

		/** Increase the number of features by 1 and insert it at last.
		 */
		void  insert_feature()
		{
			if (feat_vector.size()>0)
			{
				int n = feat_vector[feat_vector.size()-1].name + 1;
				feat_vector.resize(1+feat_vector.size());
				feat_vector[feat_vector.size()-1].name=n;
				feat_vector[feat_vector.size()-1].hits=0;
			}
			else	//es el primer elemento
			{
				feat_vector.resize(1);
				feat_vector[0].name=0;
				feat_vector[0].hits=0;
			}
		}

		/** Increase the number of features by 1 and insert it at last establishing its name and number of hits.
		 */
		void  insert_feature(const int &n, const int &h)
		{
			feat_vector.resize(1+feat_vector.size());
			feat_vector[feat_vector.size()-1].name=n;
			feat_vector[feat_vector.size()-1].hits=h;
		}

		/** Erase a feature from de vector.
		 */
		void  delete_feature(const size_t &index)
		{
			if (index>=feat_vector.size())
				THROW_EXCEPTION("Feature for delete out of bounds in CFeature::delete_feature");
			for (size_t i=index;i<feat_vector.size()-1;i++)
				feat_vector[i]=feat_vector[i+1];
			feat_vector.resize(feat_vector.size()-1);
		}

	}; // end class

} // end namespace

#endif //__CFeature_H
