//doxygen
/*! \file */

#include "cv.h"
#include "highgui.h"
#include "VisageFeaturesDetector.h"
#include "visageVision.h"
#include "Common.h"
#include "VisageDrawing.h"
#include "LicenseString.h"


#define MAX_IMAGE_SIZE 1000.0f

using namespace VisageSDK;

/**
 * VisageFeaturesDetector instance.
 */
VisageFeaturesDetector* m_Detector;
IplImage* frame;
IplImage *imageBGRA;

/**
*	Performs facial features detection on a file.

	Perform facial feature detection on the image given by fileName. If successful, return the image with the feature points drawn on top of it. Also, an FDP object is created and saved in the current working directory.
	Otherwise, return NULL.
	
	@param fileName The name of the image file to process.
	@return annotated image file if successful, NULL if not.
*
*/
IplImage* DetectFeatures(char *fileName)
{
	int value;

	// Load the image
	frame = 0;
	IplImage* frame_resized = 0;
	frame = cvLoadImage(fileName);
	
	if(!frame) 
	{
		printf("Cannot open %s\n",fileName);
		return NULL;
	}
	//cvCvtColor(frame, frame, VS_BGR2RGB);
	
	IplImage *logo = cvLoadImage("../Linux/data/images/logo.png", CV_LOAD_IMAGE_UNCHANGED);
	
	//resize the image if image is too big
	if( frame->height > MAX_IMAGE_SIZE || frame->width > MAX_IMAGE_SIZE )
	{
		float step = 1.0f;
		if( frame->height >= frame->width )
			step = MAX_IMAGE_SIZE/static_cast<float>(frame->height);
		else
			step = MAX_IMAGE_SIZE/static_cast<float>(frame->width);
		int w = static_cast<int>(static_cast<float>(frame->width)*step);
		int h = static_cast<int>(static_cast<float>(frame->height)*step);
		frame_resized = cvCreateImage(cvSize(w, h), frame->depth, frame->nChannels);
		cvResize(frame, frame_resized);
		cvReleaseImage(&frame);
	}
	else frame_resized = frame;
		

	//MORE THAN 1 FACE
	int maxFaces = 100;
	FaceData* data = new FaceData[maxFaces];
	
	value = m_Detector->detectFacialFeatures((VsImage*)frame_resized, data, maxFaces); 

	if(value > 0)
	{
		// save feature points into file
		for(int i = 0; i < value; i++)
		{
			char tmpFileName[200];
			strcpy(tmpFileName,fileName);
			if(strlen(tmpFileName)>4)
			{
				tmpFileName[strlen(tmpFileName)-4] = 0;

				char idx[10];
				sprintf(idx, "%d", i);
				strcat(tmpFileName, "_");
				strcat(tmpFileName, idx);
				strcat(tmpFileName,".fdp");
				//data[i].featurePoints2D->saveToFile(); //UN-COMMENT THIS LINE IN ORDER TO WRITE THE FDP FILE
			}
			VisageDrawing::drawResults((VsImage*)frame_resized, &data[i]);
			imageBGRA = cvCreateImage(cvSize(frame_resized->width, frame_resized->height), IPL_DEPTH_8U, 4);
			cvCvtColor(frame_resized, imageBGRA, CV_BGR2BGRA);
			if (logo)
				VisageDrawing::drawLogo((VsImage*)imageBGRA, (VsImage*)logo);
		}
	}

	delete[] data;

	return imageBGRA;
}

void help(){
	const char help[500] = \
	"Usage:\n" \
	"./runDetector imageName.jpg\n" \
	"*Working directory is being set to Samples/data folder*";
	printf("%s\n",help);
}

/*! \mainpage  visage|SDK VisageDetectorDemo example project
*
* \htmlonly
* <table border="0">
* <tr>
* <td width="32"><a href="../../../../../bin/VisageDetectorDemo"><img src="../../../../../doc/images/run_sample.png" border=0 title="Run Sample (this may not work in all browsers, in such case please run VisageDetectorDemo from the visageSDK\bin folder.)"></a></td>
* <td width="32"><a href="../../../../../bin"><img src="../../../../../doc/images/open_bin_folder.png" border=0 title="Open Executable Folder (visageSDK\bin)"></a></td>
* <td width="32"><a href="../../../data/images"><img src="../../../../../doc/images/open_data_folder.png" border=0 title="Open Data Folder"></a></td>
* <td width="32"><a href="../../../build"><img src="../../../../../doc/images/open_project_folder.png" border=0 title="Open Project Folder"></a></td>
* <td width="32"><a href="../../../source/VisageDetectorDemo"><img src="../../../../../doc/images/open_source_folder.png" border=0 title="Open Source Code Folder"></a></td>
* </tr>
* </table>
* \endhtmlonly
*
* \if REDHAT_DOXY 
* \htmlonly
* <h2>Dependencies</h2>
*
* Prerequisites to building the sample project are:
* <ul>
* <li>You should have the Software Development Workstation version of RHEL6 (you can choose the version during the installation of RHEL6)</li>
* <li>OpenGL with dynamic libraries: GL, GLU (yum install mesa-libGL-devel mesa-libGLU-devel)</li>
* <li>GCC: gcc 7.0+ (sudo yum install gcc-c++)</li>
* <li>GTK+ 2.0 with dynamic library: gtk-x11-2.0 (yum install gtk2-devel)</li>
* <ul>
*     <li> provided OpenCV library is built with GTK support</li>
*     <li>libVision library also uses GTK to display error messages</li>
* </ul>
* <li>curses terminal control library (yum install ncurses-devel)</li>
* <li>FFMPEG with dynamic libraries: swscale, avformat.</li> <br>
* FFMPEG libraries which were previously installed using ATRPMS repository are now available on ATRPMS repository mirror server. In order to install them, please do the following steps:
* <ul>
* <li>1. Install RPM repository package (this step can be skipped if you already have ATRPMS repository installed):</li>
* <ul style="list-style-type:none">
*   <li>$> sudo rpm -ivh <a href="http://ftp-stud.fht-esslingen.de/Mirrors/atrpms/dl.atrpms.net/el7-x86_64/atrpms/stable/atrpms-repo-7-7.el7.x86_64.rpm">http://ftp-stud.fht-esslingen.de/Mirrors/atrpms/dl.atrpms.net/el7-x86_64/atrpms/stable/atrpms-repo-7-7.el7.x86_64.rpm</a> </li>
* </ul>
* <li>2. Modify atrpms.repo as follows:</li>
* <ul style="list-style-type:none">
*   <li>$> sudo sed -ri 's/baseurl=(.*)/baseurl=http:\/\/ftp-stud.fht-esslingen.de\/Mirrors\/atrpms\/dl.atrpms.net\/el7-x86_64\/atrpms\/stable/g' /etc/yum.repos.d/atrpms.repo </li>
* </ul>
* <li>3. Run the following command in terminal: </li> 
* <ul style="list-style-type:none">
*   <li>$> sudo yum-config-manager --enable atrpms </li>
* </ul>
* <li>4. Install FFMPEG libraries and create required symlinks: 
* <ul style="list-style-type:none">
*   <li>$> sudo yum install libavformat55.x86_64 </li>
*   <li>$> sudo ln -s /usr/lib64/libavformat.so.55 /usr/lib64/libavformat.so </li>
*   <li>$> sudo yum install libswscale2.x86_64 </li>
*   <li>$> sudo ln -s /usr/lib64/libswscale.so.2 /usr/lib64/libswscale.so </li>
*   <li>$> sudo ln -s /usr/lib64/libjpeg.so.62 /usr/lib64/libjpeg.so </li>
*   <li>$> sudo ln -s /usr/lib64/libavutil.so.52 /usr/lib64/libavutil.so </li>
*   <li>$> sudo ln -s /usr/lib64/libavcodec.so.55 /usr/lib64/libavcodec.so </li>
* </ul>
* </ul>
* </ul>
* \endhtmlonly
* \else
* \htmlonly
* <h2>Dependencies</h2>
*
* Prerequisites to building and running the sample project are:
* <ul>
* <li>g++ compiler (versions 4.7.x) (sudo apt-get install g++)</li>
* <li>OpenGL with dynamic libraries: GL, GLU (sudo apt-get install freeglut3-dev)</li>
* <li>OpenCV library (sudo apt-get install libopencv-dev)</li>
* <li>Video4Linux library (sudo apt-get install libv4l-dev)</li>
* <li>GTK+ 2.0 with dynamic library: gtk-x11-2.0 (sudo apt-get install libgtk2.0-dev)</li>
* <li>curses terminal control library (sudo apt-get install libncurses5-dev)</li>
* <li>high level programming interface for IEEE1394 digital camera (sudo apt-get install libdc1394-22-dev)</li>
* </ul>
* </p>
* \endhtmlonly
* \endif
* \htmlonly
* <h2>Running prebuilt sample</h2>
* \endhtmlonly
*
* The VisageDetectorDemo example project demonstrates the following capabilities of visage|SDK:
*
* - facial features detection in still images
*
*
* To use the application: 
* Run the './runDetector.sh <filename>' command from the terminal\n\n
* This will perform facial features detection on a provided image (<filename>). If no image is provided detection will be performed on a default image. The sample is 
* modified to run from the visageSDK/bin folder. It changes the current directory to ../Samples/data folder where Face Detector.cfg configuration file is located. 
* Images are provided relative to that folder. The image should represent a face, in frontal pose and with a neutral expression. The face should not take a too big portion of the image,
*	  i.e., less than 50%. Several test images are available in the folder <a href="../../../data/images">Samples/Linux/data/images</a>.
*
* The specific classes and methods that demonstrate visage|SDK are:
* - main(): Initialises the Facial Feature Detector @ref m_Detector.
* - IplImage* DetectFeatures(char *fileName): Performs facial features detection on a still image and displays the result
*
* \htmlonly
* <h2>Building the project</h2>
*
* <p>
* The VisageDetectorDemo sample project source file is located in the <a href="../../../source/VisageDetectorDemo">Samples/Linux/source/VisageDetectorDemo</a> subfolder of the visage|SDK for Linux folder.
* It is built using the provided Makefile located in Samples/Linux/build subfolder.
* </p>
* The application needs to be built with license key in order to work properly. More information on how to obtain license key and include it in the application can be found 
* in <a href="../../../../../doc/licensing.html"><em>Licensing</em></a> section of the documentation.
* \endhtmlonly
*/
int main( int argc, const char* argv[] ){
	
	initializeLicenseManager(licenseKey.c_str());

	//Set current directory to data directory because Face Detector.cfg is located there
	if (chdir("../Samples/data")!=0){
		printf("Unable to change current directory.");
		help();
		return -1;
	}

	m_Detector = new VisageFeaturesDetector("Face Detector.cfg");
		
	char imageName[200] = "../Linux/data/images/faces1.jpg";
	
	if (argc == 1) {
		help();
		printf("Default image will be used - faces1.jpg\n");
	}
	else if (argc >=2) {
		printf("Detecting faces on %s ...\n",argv[1]);
		strcpy(imageName,argv[1]);
	}

	if (!m_Detector->Initialize()) {
		printf("Could not load required data files.\n");
	}
	else{
		IplImage* detected = DetectFeatures(imageName);
		cvNamedWindow("FaceDetector");
		cvShowImage("FaceDetector", detected);
		cvWaitKey(0);
		cvDestroyWindow("FaceDetector");
		cvReleaseImage(&frame);
	}
	
	return 0;
}
