
#define DECLARE_PHOTOS

#include "photos.h"
using namespace std;

Photo::Photo() {
	id = -1;
	timestamp = 0;
	face_id = -1;
}

Photo::Photo(int id, string url, time_t timestamp, vector<string> keywords) {
	this->id = id;
	this->url = url;
	this->timestamp = timestamp;
	this->keywords = keywords;

	char buffer[1000];
	sprintf(buffer, "photos/%d.jpg", this->id);
	this->filename = buffer;
}

Photo::Photo(const Photo& other) {
	id = other.id;
	keywords = other.keywords;
	url = other.url;
	timestamp = other.timestamp;
	filename = other.filename;
	face_id = other.face_id;
	face_ids = other.face_ids;
}

Photo Photo::operator=(const Photo& other) {
	id = other.id;
	keywords = other.keywords;
	url = other.url;
	timestamp = other.timestamp;
	filename = other.filename;
	face_id = other.face_id;
	face_ids = other.face_ids;
	return *this;
}

void Photo::setFaceID(int face_id) {
	this->face_id = face_id;
	system("rm /tmp/faces_tmp.txt 2>/dev/null");
	string faces_cmd =
		"ls " DATA_DIR "scaled_faces/bw/%d_* 2>/dev/null"
		" | sed -e 's/^.*_\\([0-9]*\\)\\.jpg/\\1/'"
		" >/tmp/faces_tmp.txt";
	char buffer[1000];
	sprintf(buffer, faces_cmd.c_str(), face_id);
	system(buffer);
	ifstream f("/tmp/faces_tmp.txt");
	if ( !f.good() ) {
		fprintf(stderr, "Unable to open temp file for face count.\n");
		exit(-1);
	}
	string line = "";
	getline(f, line);
	while ( line != "" ) {
		int id = 0;
		sscanf(line.c_str(), "%d", &id);
		face_ids.push_back(id);
		line = "";
		getline(f, line);
	}
	f.close();
	system("rm /tmp/faces_tmp.txt 2>/dev/null");
}

int Photo::getID() {
	return id;
}

string Photo::getURL() {
	return url;
}

time_t Photo::getTimeStamp() {
	return timestamp;
}

vector<string> Photo::getKeywords() {
	return keywords;
}

string Photo::getFileName() {
	return filename;
}

int Photo::getFaceID() {
	return face_id;
}

int Photo::getFaceCount() {
	return face_ids.size();
}

int Photo::getFaceID(int i) {
	if ( i >= face_ids.size() || i < 0 ) {
		fprintf(stderr,"photos[%d].getFaceID(%d) out of range [0..%d)\n",id,i,getFaceCount());
		exit(-1);
	}
	return face_ids[i];
}

bool Photo::hasKeyword(string keyword) {
	return find(keywords.begin(),keywords.end(),keyword) != keywords.end();
}

char* photo_query =
"    select"
"        blog_photo.id as id,"
"        blog_photo.keywords as keywords,"
"        blog_photo.url as url,"
"        blog_photo_page.tmstamp::abstime::int"
"    from"
"        blog_photo,"
"        blog_photo_page"
"    where"
"        blog_photo.deleted is null"
"        and blog_photo.page_id = blog_photo_page.id"
"    order by"
"        blog_photo_page.tmstamp,"
"        blog_photo.id";

void loadPhotos() {
	PGconn *conn = PQconnectdb("dbname=blog");
	if ( PQstatus(conn) != CONNECTION_OK ) {
		fprintf(stderr,"Unable to connect to database: %s\n", PQerrorMessage(conn));
		PQfinish(conn);
		exit(-1);
	}

	PGresult *rs = PQexec(conn, photo_query);
	if ( rs == NULL ) {
		fprintf(stderr,"Error executing query: %s\n", PQerrorMessage(conn));
		PQfinish(conn);
		exit(-1);
	}
	if ( PQresultStatus(rs) != PGRES_TUPLES_OK ) {
		fprintf(stderr,"Error executing query:\n");
		fprintf(stderr,"  Status: %s\n", PQresStatus(PQresultStatus(rs)));
		fprintf(stderr,"  Error: %s\n", PQresultErrorMessage(rs));
		PQclear(rs);
		PQfinish(conn);
		exit(-1);
	}

	int photo_count = PQntuples(rs);
	for ( int i=0; i<photo_count; i++ ) {
		char* s_id = PQgetvalue(rs,i,0);
		char* s_keywords = PQgetvalue(rs,i,1);
		char* s_url = PQgetvalue(rs,i,2);
		char* s_timestamp = PQgetvalue(rs,i,3);

		int id = atoi(s_id);
		string url = s_url;
		time_t timestamp = atoi(s_timestamp);
		// split keywords
		vector<string> keywords;
		char* buffer = (char*)malloc(strlen(s_keywords)+1);
		strcpy(buffer,s_keywords);
		char* keyword = buffer;
		while ( keyword != NULL ) {
			char* next_keyword = strchr(keyword,' ');
			if ( next_keyword != NULL ) {
				*(next_keyword++) = '\0';
			}
			keywords.push_back(keyword);
			keyword = next_keyword;
		}
		free(buffer);

		Photo photo(id,url,timestamp,keywords);
		photos.push_back(photo);
	}
	PQclear(rs);
	PQfinish(conn);
	conn = NULL;

	ifstream f(DATA_DIR "labeled_faces/matches.html");
	if (!f.good()) {
		fprintf(stderr, "unable to open " DATA_DIR "labeled_faces/matches.html\n");
		exit(-1);
	}
	string line = "";
	getline(f,line);
	while ( f.good() ) {
		regex_t regexp;
		if ( !regcomp( &regexp, "<!-- MAP: \\([0-9]*\\) -> \\([0-9]*\\) -->", 0 ) ) {
			int nm = regexp.re_nsub;
			regmatch_t* matches = new regmatch_t[nm+1];
			if ( !regexec( &regexp, line.c_str(), nm+1, matches, 0 ) ) {
				int old_id = atoi(line.substr(matches[1].rm_so,matches[1].rm_eo-matches[1].rm_so).c_str());
				int new_id = atoi(line.substr(matches[2].rm_so,matches[2].rm_eo-matches[2].rm_so).c_str());
				for ( int i=0; i<photos.size(); i++ ) {
					if ( photos[i].getID() == old_id ) {
						photos[i].setFaceID(new_id);
					}
				}
			}
		} else {
			fprintf(stderr, "unable to compile regular expression\n");
			exit(-1);
		}
		line = "";
		getline(f,line);
	}
	f.close();
}

