// FaceCutter.cpp : main project file.

#include <FaceClassifier/miscellaneous.h>

#include <iostream>
#include <sstream>
#include <string>
#include <fstream>

std::string upperCase(const std::string str) {
	char *ret = (char*)malloc((str.length() + 1) * sizeof(char));
	strcpy(ret, str.c_str());
	unsigned int i;
	for (i = 0; i < strlen(ret); i++) {
		ret[i] = toupper(ret[i]);
	}
	return std::string(ret);
}

int main(int argc, char *argv[])
{
	bool grayscaling = true;
	int width, height;
	if (argc != 4) {
		std::cout << "Usage: facecutter.exe source_dir destination_dir list_of_source_files\n";
		exit(-1);
	}
	if (!face::utils::FileSystemUtils::exists(std::string(argv[3]))) {
		std::runtime_error("Error! File of source files doesn't exist: " + std::string(argv[3]) + ".\n");
		exit(-1);
	}
	int failed = 0;
	misc::FaceDetector fd;
	face::utils::Configuration config;
	config.load("../../.config/facecutter.conf");
	fd.Load(config["haarcascade"].get());
	if (config["image"]["grayscaling"].get().compare("yes") == 0) grayscaling = true;
	if (config["image"]["grayscaling"].get().compare("no") == 0) grayscaling = false;
	width = face::utils::StringUtils::parse<int>(config["image"]["width"].get());
	height = face::utils::StringUtils::parse<int>(config["image"]["height"].get());

	IplImage *img, *grayImg, *subImg, *resultImg;
	CvSeq *seq;
	std::string output;
	std::string inputPrefix = std::string(argv[1]);
	std::string inputWithoutPrefix;
	std::string destDir = std::string(argv[2]);
	std::string destSubDir;
	std::list<std::string> fileList;
	misc::getLines(std::string(argv[3]), &fileList);
	std::list<std::string>::iterator itr;
	std::string sysCmd;

	for (itr = fileList.begin(); itr != fileList.end(); itr++) {
		inputWithoutPrefix = (*itr).substr(inputPrefix.length());
		output = destDir + inputWithoutPrefix;
		output = output.substr(0, output.find_last_of(".") + 1) + "png";
		destSubDir = output.substr(0, output.find_last_of(face::utils::FileSystemUtils::DIRECTORY_SEPARATOR));
		sysCmd = "if not exist " + destSubDir + " md " + destSubDir;
		system(sysCmd.c_str());
		std::cout << output << ": ";

		if (upperCase(inputPrefix).compare(upperCase((*itr).substr(0, inputPrefix.length())))) {
			std::cout << "\n" << inputPrefix << " !=\n" << (*itr).c_str();
			std::cout << "skipped\n";
			continue;
		}
		if (!face::utils::FileSystemUtils::exists(*itr)) {
			std::cout << itr->c_str() << "doesn't exists\n";
			failed++;
			continue;
		}
		img = cvLoadImage(itr->c_str());
		if (img == NULL) {
			std::cout << itr->c_str() << "couldn't be loaded\n";
			failed++;
			continue;
		}

		grayImg = cvLoadImage(itr->c_str(), 0);

		seq = fd.DetectFaces(grayImg);
		if (!seq || seq->total != 1) {
			std::cout << "is not a face\n";
			failed++;
			continue;
		}
		if (grayscaling) {
			subImg = misc::clipSubImg(grayImg, (CvRect*)cvGetSeqElem(seq, 0));
		} else {
			subImg = misc::clipSubImg(img, (CvRect*)cvGetSeqElem(seq, 0));
		}
		if (width != 0 && height != 0) {
			resultImg = cvCreateImage(cvSize(width, height), subImg->depth, subImg->nChannels);
			cvResize(subImg, resultImg);
		}
			else
		{
			resultImg = subImg;
		}
		cvSaveImage((char*)(void*)output.c_str(), resultImg);
		std::cout << "done\n";
		cvReleaseImage(&img);
		cvReleaseImage(&subImg);
	}
	std::cout << "\nReady.\n";
    return 0;
}
