#include "Partition.h"

using namespace std;

vector<vector<int>>  divide_scape_NINE_parts(string foldername, int meshno){ //divide scape model to 9 parts
	Mesh* mesh = new Mesh();
	vector<vector<int>> parts_vertlists(9);

	string format = "scape";
	mesh->readID(meshno, foldername, format);

	cout << "dividing" << endl;

	for (unsigned int i = 0; i < mesh->verts.size(); i++){

		if (mesh->verts[i]->coords[0] > 0.85f) {//top
			if (mesh->verts[i]->coords[2] > 0.25f) {//arm1
				if (mesh->verts[i]->coords[0] > 1.44f)
					parts_vertlists[0].push_back(i);
				else
					parts_vertlists[7].push_back(i);
			}
			else if (mesh->verts[i]->coords[2] < -0.15f) {//arm2
				if (mesh->verts[i]->coords[0] > 1.44f)
					parts_vertlists[5].push_back(i);
				else
					parts_vertlists[6].push_back(i);
			}
			else
				parts_vertlists[4].push_back(i);
		}
		else{ //bottom
			if (mesh->verts[i]->coords[0] > 0.48f) {//topleg
				if (mesh->verts[i]->coords[2] > 0.05)
					parts_vertlists[1].push_back(i);
				else
					parts_vertlists[2].push_back(i);
			}
			else{//bottomleg
				if (mesh->verts[i]->coords[2] > 0.05)
					parts_vertlists[3].push_back(i);
				else
					parts_vertlists[8].push_back(i);
			}
		}
	}
	return parts_vertlists;
}

vector<vector<int>> divide_scape_FIVE_parts(string foldername, int meshno){ //divide scape model to 5 parts
	Mesh* mesh = new Mesh();
	vector<vector<int>> parts_vertlists(5);

	string format = "scape";
	mesh->readID(meshno, foldername, format);

	cout << "dividing" << endl;
	for (unsigned int i = 0; i < mesh->verts.size(); i++){

		if (mesh->verts[i]->coords[0] > 0.85f) {//top
			if (mesh->verts[i]->coords[2] > 0.25f) {//arm1
				parts_vertlists[0].push_back(i);
			}
			else if (mesh->verts[i]->coords[2] < -0.15f) {//arm2
				parts_vertlists[1].push_back(i);
			}
			else
				parts_vertlists[2].push_back(i); //torso and head
		}
		else{ //bottom

			if (mesh->verts[i]->coords[2]>0.05)
				parts_vertlists[4].push_back(i);
			else
				parts_vertlists[3].push_back(i);
		}
	}

	return parts_vertlists;
}

vector<vector<int>> divide_scape_TWO_parts(string foldername, int meshno){ //divide scape model to 5 parts
	Mesh* mesh = new Mesh();
	vector<vector<int>> parts_vertlists(2);
	string format = "scape";
	mesh->readID(meshno, foldername, format);

	cout << "dividing" << endl;
	vector<int> vint1, vint2;
	for (unsigned int i = 0; i < mesh->verts.size(); i++){

		if (mesh->verts[i]->coords[0] < 1.08)
			parts_vertlists[0].push_back(i);

		else //bottom
			parts_vertlists[1].push_back(i);
	}

	return parts_vertlists;
}

vector<vector<int>> divide_hand_SIX_parts(string foldername, int meshno) { //divide hand model to 6 parts
	Mesh* mesh = new Mesh();
	vector<vector<int>> parts_vertlists(6);
	string format = "hand";
	mesh->readID(meshno, foldername, format);

	cout << "dividing" << endl;
	for (unsigned int i = 0; i < mesh->verts.size(); i++) {
		if (mesh->verts[i]->coords[0] > 0.31) {//thumb
			parts_vertlists[0].push_back(i);
		}
		else {//palm
			if (mesh->verts[i]->coords[1] > 0.17) {//fingers
				if (mesh->verts[i]->coords[0] > 0) {//index finger
					parts_vertlists[1].push_back(i);
				}
				else {
					if (mesh->verts[i]->coords[0] > -0.225) {//middle finger
						if (mesh->verts[i]->coords[0] < -0.18 && mesh->verts[i]->coords[1] < 0.35) { // correction on ring finger
							parts_vertlists[3].push_back(i);
						}
						else {
							parts_vertlists[2].push_back(i);
						}
					}
					else {
						if (mesh->verts[i]->coords[0] > -0.44) {//ring finger
							parts_vertlists[3].push_back(i);
						}
						else {//little finger
							if (mesh->verts[i]->coords[1] > 0.35) { // correction on ring finger
								parts_vertlists[3].push_back(i);
							}
							else {//little finger
								parts_vertlists[4].push_back(i);
							}
						}
					}
				}
			}
			else {//palm
				if (mesh->verts[i]->coords[0] < -0.3 && mesh->verts[i]->coords[1] > -0.05) {//correction on little finger
					parts_vertlists[4].push_back(i);
				}
				else if (mesh->verts[i]->coords[0] < -0.225 && mesh->verts[i]->coords[1] > 0.08) {//correction on ring finger
					parts_vertlists[3].push_back(i);
				}
				else {
					parts_vertlists[5].push_back(i);
				}
			}
		}
	}
	int totalverts = 0;
	for (unsigned int i = 0; i < parts_vertlists.size(); i++) {
		totalverts += parts_vertlists[i].size();
	}
	cout << "totalverts: " << totalverts << "mesh vert size: " << mesh->verts.size() << endl;
	return parts_vertlists;

}

vector<vector<int>> divide_hand_ELEVEN_parts(string foldername, int meshno, const vector<vector<int>>&inputlist) { //divide hand model to 11 parts
	//now, divide the fingers into two parts
	Mesh* mesh = new Mesh();
	vector<vector<int>> parts_vertlists(11);
	string format = "hand";
	mesh->readID(meshno, foldername, format);
	//divide thumb
	for (unsigned int i = 0; i < inputlist[0].size(); i++) {
		if (mesh->verts[inputlist[0][i]]->coords[0] > 0.4 && mesh->verts[inputlist[0][i]]->coords[1] > -0.04) {//thumb
			parts_vertlists[0].push_back(inputlist[0][i]);
		}
		else {
			parts_vertlists[1].push_back(inputlist[0][i]);
		}
	}
	for (unsigned int i = 0; i < inputlist[1].size(); i++) { //index finger
		if (mesh->verts[inputlist[1][i]]->coords[1] > 0.45)
			parts_vertlists[2].push_back(inputlist[1][i]);
		else
			parts_vertlists[3].push_back(inputlist[1][i]);
	}
	for (unsigned int i = 0; i < inputlist[2].size(); i++) { //middle finger
		if (mesh->verts[inputlist[2][i]]->coords[1] > 0.45)
			parts_vertlists[4].push_back(inputlist[2][i]);
		else
			parts_vertlists[9].push_back(inputlist[2][i]);
	}
	for (unsigned int i = 0; i < inputlist[3].size(); i++) { //ring finger
		if (mesh->verts[inputlist[3][i]]->coords[1] > 0.33 && mesh->verts[inputlist[3][i]]->coords[0] < -0.25)
			parts_vertlists[6].push_back(inputlist[3][i]);
		else
			parts_vertlists[7].push_back(inputlist[3][i]);
	}
	for (unsigned int i = 0; i < inputlist[4].size(); i++) { //little finger
		if (mesh->verts[inputlist[4][i]]->coords[1] > 0.1 && mesh->verts[inputlist[4][i]]->coords[0] < -0.45)
			parts_vertlists[8].push_back(inputlist[4][i]);
		else
			parts_vertlists[10].push_back(inputlist[4][i]);
	}
	for (unsigned int i = 0; i < inputlist[5].size(); i++) { //palm
		parts_vertlists[5].push_back(inputlist[5][i]);
	}
	return parts_vertlists;
}

vector<vector<int>>  divide_horse(string foldername, int meshno) { //divide horse model to 6 parts

	Mesh* mesh = new Mesh();
	vector<vector<int>> parts_vertlists(7);

	string format = "horse";
	mesh->readID(meshno, foldername, format);

	cout << "dividing" << endl;//coords[1]->vertical , coords[2]->horizontal
	for (unsigned int i = 0; i < mesh->verts.size(); i++) {
		if (mesh->verts[i]->coords[1] > 0.5 && mesh->verts[i]->coords[2] >	 0.1) {//head
			parts_vertlists[0].push_back(i);
		}
		else {
			if (mesh->verts[i]->coords[1] < 0.33) {//paws
				if (mesh->verts[i]->coords[2] > 0.05) {//front
					if (mesh->verts[i]->coords[0] > 0) {//left right
						parts_vertlists[1].push_back(i);
					}
					else {
						parts_vertlists[2].push_back(i);
					}
				}
				else {//back
					if (mesh->verts[i]->coords[2] > -0.4) {//divide tail
						if (mesh->verts[i]->coords[0] > 0) {
							parts_vertlists[3].push_back(i);
						}
						else
							parts_vertlists[4].push_back(i);
					}
					else
						parts_vertlists[6].push_back(i);
				}
			}
			else {
				if (mesh->verts[i]->coords[2] > -0.41)//divide tail
					parts_vertlists[5].push_back(i);
				else
					parts_vertlists[6].push_back(i);
			}
		}
	}
	int totalverts = 0;
	for (unsigned int i = 0; i < parts_vertlists.size(); i++) {
		totalverts += parts_vertlists[i].size();
	}
	cout << "totalverts: " << totalverts << "mesh vert size: " << mesh->verts.size() << endl;
	return parts_vertlists;

}


vector<vector<int>>  divide_cat(string foldername, int meshno) { //divide hand model to 6 parts

	Mesh* mesh = new Mesh();
	vector<vector<int>> parts_vertlists(5);

	string format = "cat";
	mesh->readID(meshno, foldername, format);

	cout << "dividing" << endl;//coords[1]->vertical , coords[2]->horizontal
	for (unsigned int i = 0; i < mesh->verts.size(); i++) {
		if (mesh->verts[i]->coords[2] > 0.24) {//head
			parts_vertlists[0].push_back(i);
		}
		else {
			if (mesh->verts[i]->coords[1] < 0.2) {//paws
				if (mesh->verts[i]->coords[2] > 0.12) {//front
					parts_vertlists[1].push_back(i);
				}
				else {
					if (mesh->verts[i]->coords[2] < -0.02)//back
						parts_vertlists[2].push_back(i);
					else {
						parts_vertlists[3].push_back(i);
					}
				}
			}
			else {
				if (mesh->verts[i]->coords[2] < -0.18) {//tail

					parts_vertlists[4].push_back(i);
				}
				else//body
					parts_vertlists[3].push_back(i);
			}
		}
	}
	int totalverts = 0;
	for (unsigned int i = 0; i < parts_vertlists.size(); i++) {
		totalverts += parts_vertlists[i].size();
	}
	cout << "totalverts: " << totalverts << "mesh vert size: " << mesh->verts.size() << endl;
	return parts_vertlists;

}


vector<vector<int>>  divide_dancer(string foldername, int meshno) { 
	Mesh* mesh = new Mesh();
	vector<vector<int>> parts_vertlists(7);

	string format = "dancer";
	mesh->readID(meshno, foldername, format);
	CenterMesh(mesh);

	cout << "dividing" << endl;
	for (unsigned int i = 0; i < mesh->verts.size(); i++) {
		if (mesh->verts[i]->coords[1] > 0.6) {//head
			parts_vertlists[0].push_back(i);
		}
		else {
			if (mesh->verts[i]->coords[2] < -0.15 && mesh->verts[i]->coords[1] > 0.1) {//right arm
				parts_vertlists[1].push_back(i);
			}
			else if (mesh->verts[i]->coords[2] < -0.26)//right arm
				parts_vertlists[1].push_back(i);

			else if (mesh->verts[i]->coords[2] < 0.17 && mesh->verts[i]->coords[1] > 0.1) {//torso
				parts_vertlists[2].push_back(i);
			}
			else if (mesh->verts[i]->coords[2] > 0.17 && mesh->verts[i]->coords[1] > 0.11) {//left arm
				parts_vertlists[3].push_back(i);
			}
			else if (mesh->verts[i]->coords[2] > 0.21 && mesh->verts[i]->coords[1] > -0.1) {//left arm
				parts_vertlists[3].push_back(i);
			}
			else if (mesh->verts[i]->coords[1] > -0.418) {//skirt
				parts_vertlists[4].push_back(i);
			}
			else {//legs
				if (mesh->verts[i]->coords[2] > -0.01) {

					parts_vertlists[5].push_back(i);
				}
				else
					parts_vertlists[6].push_back(i);
			}
		}
	}
	int totalverts = 0;
	for (unsigned int i = 0; i < parts_vertlists.size(); i++) {
		totalverts += parts_vertlists[i].size();
	}
	cout << "totalverts: " << totalverts << "mesh vert size: " << mesh->verts.size() << endl;
	return parts_vertlists;
}


vector<vector<int>>  divide(string foldername, string format, int noofparts) { //divide model
	cout << "dividing " << format << " into " << noofparts << " parts" << endl;
	vector<vector<int>> parts_vertlists;
	if (format == "scape") {
		if (noofparts == 9)
			parts_vertlists = divide_scape_NINE_parts(foldername, 38);// //divide scape model to 9 parts
		else if (noofparts == 5)
			parts_vertlists = divide_scape_FIVE_parts(foldername, 38);// //divide scape model to 5 parts
		else if (noofparts == 2)
			parts_vertlists = divide_scape_TWO_parts(foldername, 21);// //divide scape model to 2 parts
		else {
			cout << "invalid number of parts" << endl;
		}
	}
	else if (format == "hand") {
		if (noofparts == 6)
			parts_vertlists = divide_hand_SIX_parts(foldername, 6);
		else if (noofparts == 11) {
			vector<vector<int>> parts_vertlists_6 = divide_hand_SIX_parts(foldername, 6);
			parts_vertlists = divide_hand_ELEVEN_parts(foldername, 6, parts_vertlists_6);// //divide 6 parts to 11 parts
		}
		else {
			cout << "invalid number of parts" << endl;
		}
	}
	else if (format == "horse") {
		if (noofparts != 7) {
			cout << "invalid number of parts" << endl;
		}
		else
			parts_vertlists = divide_horse(foldername, 0);
	}
	else if (format == "cat") {
		if (noofparts != 5) {
			cout << "invalid number of parts" << endl;
		}
		else parts_vertlists = divide_cat(foldername, 0);
	}
	else if (format == "dancer") {
		if (noofparts != 7) {
			cout << "invalid number of parts" << endl;
		}
		else parts_vertlists = divide_dancer(foldername, 0);
	}

	return parts_vertlists;
}