#include "FloodFill.h"
#include "BoundingBox.h"


FloodFill::FloodFill()
{
}


FloodFill::~FloodFill()
{
}

int FloodFill::enclosedPixels(const vector<Point>& contourVec, vector<Point> & regionPixels)
{
	Point p = findStartPoint(contourVec);
	regionPixels.push_back(p);

	floodfill(contourVec, regionPixels, p);

	return 1;
}

int FloodFill::floodfill(const vector<Point> & contourVec, vector<Point> & regionPixels, Point &p)
{
	//Check four-connected
	int pointsx[] = {0, 1, 0, -1};
	int pointsy[] = {-1, 0, 1, 0};

	for (int i = 0; i < 4; i++)
	{
		Point check = Point(p.x + pointsx[i], p.y + pointsy[i]);
		
		if (contains(contourVec, check))
		{
			continue;
		}
		else if (contains(regionPixels, check))
		{
			continue;
		}
		else
		{
			regionPixels.push_back(check);
			floodfill(contourVec, regionPixels, check);
		}
	}

	return 1;
}

Point FloodFill::findStartPoint(vector<Point> vec)
{
	int maxy = INT_MIN, maxx = INT_MIN, miny = INT_MAX, minx = INT_MAX;

	for (Point p : vec)
	{
		if (p.y > maxy)
			maxy = p.y;

		if (p.y < miny)
			miny = p.y;

		if (p.x > maxx)
			maxx = p.x;

		if (p.x < minx)
			minx = p.x;
	}

	int centery = (maxy + miny) / 2;

	int x1 = 0, x2 = 0;

	for (int x = minx; x <= maxx; x++)
	{
		if (contains(vec, Point(x, centery)))
		{
			if (x1 == 0)
			{
				x1 = x;
			}
			else
			{
				x2 = x;
				break;
			}
		}
	}

	int centerx = (x1 + x2) / 2;
	Point start = Point(centerx, centery);

	return start;
}

bool FloodFill::contains(vector<Point> vec, Point p)
{
	for (Point pnt : vec)
	{
		if (pnt.x == p.x && pnt.y == p.y)
			return true;
	}

	return false;
}


int FloodFill::split(const vector<vector<Point>> & contours, const Mat &image, string filename)
{
	//Create filenames
	std::string base_filename = filename.substr(filename.find_last_of("/\\") + 1);
	std::string::size_type const p(base_filename.find_last_of('.'));
	std::string name = base_filename.substr(0, p);

	vector<vector<Point>> regions;
	regions.resize(contours.size());

	for (int i = 0; i < contours.size(); i++)
	{
		vector<Point> temp;
		enclosedPixels(contours[i], temp);
		regions[i] = temp;
	}
	

	vector<vector<Point>> bounds;
	BoundingBox::allBoundingBoxes(contours, bounds);

	//Find largest bounding box
	Size largest = Size(0, 0);
	for (vector<Point> box : bounds)
	{
		int height = abs(box[2].y - box[1].y);
		int width = abs(box[1].x - box[0].x);

		if (height > largest.height)
			largest.height = height;
		if (width > largest.width)
			largest.width = width;
	}

	int nr = 0;

	//Create every image
	for (int i = 0; i < contours.size(); i++)
	{
		// Creeer een witte image
		IplImage* iplimage = cvCreateImage(cvSize(image.cols, image.rows), IPL_DEPTH_8U, 3);
		Mat resultImage = cvarrToMat(iplimage);
		resultImage = Scalar(255, 255, 255);

		//Kopieren van pixels
		for (Point p : regions[i])
		{
			resultImage.at<uchar>(p) = image.at<uchar>(p);
		}
		for (Point p : contours[i])
		{
			resultImage.at<uchar>(p) = image.at<uchar>(p);
		}

		Point center = Point((bounds[i][0].x + bounds[i][2].x) / 2, (bounds[i][0].y + bounds[i][2].y) / 2);

		Rect r = Rect(center.x - (largest.width / 2), center.y - (largest.height / 2), largest.width, largest.height);
		Mat roi(resultImage, r);

		imwrite("output/" + name + "_" + to_string(nr) + ".bmp", roi);

		nr++;
	}

	return 1;
}