package cz.vutbr.feec.imageprocessing.op.segmentation.watershed;

import java.awt.Color;
import java.util.ArrayList;

public class Region {

	private int regionId;
	private int numOfPointsInRegion;
	private ArrayList<WPoint> points;
	private ArrayList<Region> neighboringRegions;
	private double sumRed;
	private double sumGreen;
	private double sumBlue;
	
	
	//constructors
	public Region(int regionId) {
		this.regionId = regionId;
		this.numOfPointsInRegion = 0;
		this.points = new ArrayList<WPoint>();
		this.neighboringRegions = new ArrayList<Region>();
		this.sumRed = 0;
		this.sumGreen = 0;
		this.sumBlue = 0;
		
	}
	
	public int getNumOfPointsInRegion() {
		return numOfPointsInRegion;
	}
		
	public void addPoint(WPoint point) {
		points.add(point);
		point.setLabel(regionId);
		numOfPointsInRegion++;
		sumRed += point.getRed();
		sumGreen += point.getGreen();
		sumBlue += point.getBlue();
	}
	
	public void removePoint(WPoint point) {
		points.remove(point); 
		numOfPointsInRegion--;
		sumRed -= point.getRed();
		sumGreen -= point.getGreen();
		sumBlue -= point.getBlue();
	}
	
	public double getAvgRed() {
		return sumRed / numOfPointsInRegion;
	}
	
	public double getAvgGreen() {
		return sumGreen / numOfPointsInRegion;
	}
	
	public double getAvgBlue() {
		return sumBlue / numOfPointsInRegion;
	}
	
	public int getRegionId() {
		return regionId;
	}
	
	public Color getAvgColor() {
		return new Color((int)getAvgRed(), (int) getAvgGreen(),(int) getAvgBlue());
	}
	
	
	public ArrayList<WPoint> getPoints() {
			return points;
	}

	public void connect(Region region2) {
		while (!region2.getPoints().isEmpty())
		{
			WPoint point = region2.getPoints().get(0);
			this.addPoint(point);
			region2.removePoint(point);
		}
	}

	public ArrayList<Region> getNeighboringRegions() {
		return neighboringRegions;
	}
	
	public void addNeigboringRegion (Region neighboringRegion) {
		if (!neighboringRegions.contains(neighboringRegion)) {
			neighboringRegions.add(neighboringRegion);
		}
	}
	
	
	
	public void removeNeighboringRegion (Region neighboringRegion) {
		neighboringRegions.remove(neighboringRegions.indexOf(neighboringRegion));
	}

	
	public Region findMostSimilarRegion() {
		Region similarRegion=null;
		float dSimilar=16581375;
		for (Region neighbor : this.getNeighboringRegions()) {
			float value = this.compare(neighbor);
			if (dSimilar>value) {
				dSimilar=value;
				similarRegion=neighbor;
			}
		}
		
		return similarRegion;
	}


	public void remapNeighboringRegions(Region region2) {
		this.removeNeighboringRegion(region2);
		region2.removeNeighboringRegion(this);
		
		while (!region2.getNeighboringRegions().isEmpty()) {
			Region curReg = region2.getNeighboringRegions().get(0);
			this.addNeigboringRegion(curReg);
			curReg.addNeigboringRegion(this);
			curReg.removeNeighboringRegion(region2);
			region2.removeNeighboringRegion(curReg);
		}
	}


	public boolean isRegionSimilar(int mergingThr, Region neigRegion) {
		if (mergingThr > (this.compare(neigRegion))) return true;
		return false;
	}

	private float compare(Region neigRegion) {
		float dRed   = (float) Math.abs(neigRegion.getAvgRed() - this.getAvgRed());
		float dGreen = (float) Math.abs(neigRegion.getAvgGreen() - this.getAvgGreen());
		float dBlue  = (float) Math.abs(neigRegion.getAvgBlue() - this.getAvgBlue());
		return dRed*dGreen*dBlue;
	}
}
