/*
 *  Brno University of Technology
 *
 *  Copyright (C) 2009-2010 by Brno University of Technology and the contributors
 *
 *  Complete list of developers available at our web site:
 *
 *       http://spl.utko.feec.vutbr.cz
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU Affero General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU Affero General Public License for more details.
 *
 *  You should have received a copy of the GNU Affero General Public License
 *  along with this program.  If not, see http://www.gnu.org/licenses/.
 */
package cz.vutbr.feec.utko.opencv.operators.imageProcessing;

import java.util.List;

import static com.googlecode.javacv.cpp.opencv_imgproc.*;
import com.googlecode.javacv.cpp.opencv_core.CvPoint;
import com.googlecode.javacv.cpp.opencv_core.CvScalar;
import com.googlecode.javacv.cpp.opencv_core.IplImage;
import com.rapidminer.operator.OperatorDescription;
import com.rapidminer.operator.OperatorException;
import com.rapidminer.parameter.ParameterType;
import com.rapidminer.parameter.ParameterTypeBoolean;
import com.rapidminer.parameter.ParameterTypeCategory;
import com.rapidminer.parameter.ParameterTypeInt;

public class FloodFill extends BaseProcessingOperator{

	private static final String START_POINT_X = "Start point x";
	private static final String START_POINT_Y = "Start point y";
	
	private static final String TARGET_COLOR_R = "Target color red";
	private static final String TARGET_COLOR_G = "Target color green";
	private static final String TARGET_COLOR_B = "Target color blue";
	
	private static final String LOW_COLOR_R = "Lower offset red";
	private static final String LOW_COLOR_G = "Lower offset green";
	private static final String LOW_COLOR_B = "Lower offset blue";
	
	private static final String UP_COLOR_R = "Upper offset red";
	private static final String UP_COLOR_G = "Upper offset green";
	private static final String UP_COLOR_B = "Upper offset blue";
	
	private static final String TYPE_OF_NEIGHBORS = "Neighbor fill";
	private static final String[] TYPES_OF_NEIGHBORS = new String[] { "4-neighbors", "8-neighbors"};
	
	public static final int NEIGHBORS4 = 0;
	public static final int NEIGHBORS8 = 1;
	public static final int NEIGHBOR4 = 4;
	public static final int NEIGHBOR8 = 8;
	
	private static final String FIXED_RANGE = "Fixed range";
	
	public FloodFill(OperatorDescription description) {
		super(description);
	}
	
	@Override
	public IplImage doWork(IplImage orig) throws OperatorException {
		IplImage cvImg = orig.clone();
		
		CvPoint seedPoint = new CvPoint(getParameterAsInt(START_POINT_X), getParameterAsInt(START_POINT_Y));
		
		CvScalar targetColor = new CvScalar();
		targetColor.red(getParameterAsInt(TARGET_COLOR_R));
		targetColor.green(getParameterAsInt(TARGET_COLOR_G));
		targetColor.blue(getParameterAsInt(TARGET_COLOR_B));
		
		CvScalar lowerColor = new CvScalar();
		lowerColor.red(getParameterAsInt(LOW_COLOR_R));
		lowerColor.green(getParameterAsInt(LOW_COLOR_G));
		lowerColor.blue(getParameterAsInt(LOW_COLOR_B));
		
		CvScalar upperColor = new CvScalar();
		upperColor.red(getParameterAsInt(UP_COLOR_R));
		upperColor.green(getParameterAsInt(UP_COLOR_G));
		upperColor.blue(getParameterAsInt(UP_COLOR_B));
		
		int flags = 0;
		
		if(getParameterAsInt(TYPE_OF_NEIGHBORS)== NEIGHBORS4){
			flags = NEIGHBOR4;
		} else {
			flags = NEIGHBOR8;
		}
		
		if(getParameterAsBoolean(FIXED_RANGE)){
			flags += CV_FLOODFILL_FIXED_RANGE;
		}
		
		//TODO pridat moznost CvConnectedComp misto null
		//TODO moznost zpracovani masky (posledni argument null) s parametrem CV_FLOODFILL_MASK_ONLY
		cvFloodFill(cvImg, seedPoint, targetColor, lowerColor, upperColor, null, flags, null);
		
		return cvImg;
	}
	
	@Override
	public List<ParameterType> getParameterTypes() {
		List<ParameterType> p = super.getParameterTypes();
		p.add(new ParameterTypeInt(START_POINT_X, "X starting point for flood fill.",0, 9999999));
		p.add(new ParameterTypeInt(START_POINT_Y, "Y starting point for flood fill.",0, 9999999));
		p.add(new ParameterTypeInt(START_POINT_Y, "Y starting point for flood fill.",0, 9999999));
		p.add(new ParameterTypeInt(TARGET_COLOR_R, "Red channel of target region.",0, 255, 255));
		p.add(new ParameterTypeInt(TARGET_COLOR_G, "Green channel of target region.",0, 255, 255));
		p.add(new ParameterTypeInt(TARGET_COLOR_B, "Blue channel of target region.",0, 255, 255));
		p.add(new ParameterTypeInt(LOW_COLOR_R, "Red lower offset used in color selection.",0, 255, 0, true));
		p.add(new ParameterTypeInt(LOW_COLOR_G, "Green lower offset used in color selection.",0, 255, 0, true));
		p.add(new ParameterTypeInt(LOW_COLOR_B, "Blue lower offset used in color selection.",0, 255, 0, true));
		p.add(new ParameterTypeInt(UP_COLOR_R, "Red upper offset used in color selection.",0, 255, 0, true));
		p.add(new ParameterTypeInt(UP_COLOR_G, "Green upper offset used in color selection.",0, 255, 0, true));
		p.add(new ParameterTypeInt(UP_COLOR_B, "Blue upper offset used in color selection.",0, 255, 0, true));
		
		p.add(new ParameterTypeCategory(TYPE_OF_NEIGHBORS,
				"If set to 4-neighbors, only horizontal and vertical neighbors to the current pixel are considered in the fi lling process; if set to 8-neighbprs, flood fill will additionally include diagonal neighbors.",
				TYPES_OF_NEIGHBORS, 0));
		p.add(new ParameterTypeBoolean(FIXED_RANGE, "(Fill relative to the start point pixel value; otherwise, fill relative to the neighbor’s value", true));
		return p;
	}
	
}
