package segmentation;

import GUI.FileChooser;
import GUI.Result;
import GUI.internalFrame;
import GUI.mainWindow;
import ij.*;
import ij.gui.NewImage;
import ij.process.ImageProcessor;

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

public class Separation {
	
	ImagePlus imp, impOtsu, impnew;
	ImageProcessor ip, nipOtsu, nipnew;
	ImagePlus imp2 = NewImage.createRGBImage ("Line Segmentation", 10, 10, 1, NewImage.FILL_WHITE);
	ImageProcessor nip = imp2.getProcessor();
	int numberResult;
	boolean draw;
	boolean setSelected;
	
	public Separation(ImagePlus imp, ImageProcessor ip, ImagePlus impOtsu, int numberResult, boolean draw, boolean setSelected) {

		this.imp = imp;
		this.ip = ip;
		this.impOtsu = impOtsu;
		nipOtsu = impOtsu.getProcessor();	
		this.numberResult = numberResult;
		this.draw = draw;
		this.setSelected = setSelected;
	}
	
	public void run(){
		
		impnew = NewImage.createRGBImage ("Line Segmentation", ip.getWidth(),ip.getHeight(), 1, NewImage.FILL_WHITE);		
		nipnew = impnew.getProcessor();	
		
		int height = 0;
		ArrayList sepI = new ArrayList();
		ArrayList sepJ = new ArrayList();
		//ArrayList redJ = new ArrayList();
		
		int color = ((Color.red.getRed() & 0xff) << 16) + ((0 & 0xff) << 8) + (0 & 0xff);
		int color2 = ((0 & 0xff) << 16) + ((Color.green.getGreen() & 0xff) << 8) + (0 & 0xff);
	//	System.out.println("color "+color);
		ArrayList white_i, white_j;
		white_i = new ArrayList();
		white_j = new ArrayList();
		int max = 0;
		
		int i = 0;
		int j = 0;
		int oldMax = 0;
		int p = 0;
		
		ArrayList<ArrayList> redLinesI = new ArrayList();
		ArrayList<ArrayList> redLinesJ = new ArrayList();
		
		ArrayList redLinI = new ArrayList();
		ArrayList redLinJ = new ArrayList();
		ArrayList maxHeight = new ArrayList();
		ArrayList minHeight = new ArrayList();
		minHeight.add(0);
		int count = 0;
		
		while (j < ip.getHeight()) {
/*			if (j > 600)
				System.out.println("ZASEKAVAM SA??separ1");*/
			
			if (ip.getPixel(i, j) == color) {
				//System.out.println("j "+j);
				
				count++;//dalsia nova cervena ciara
			//	System.out.println("count "+count);
				int redI = i;
				int redJ = j;
				redLinI = new ArrayList();
				redLinJ = new ArrayList();
				
				redLinI.add(redI);
				redLinJ.add(redJ);
//				System.out.println(redLinI.get(redLinI.size() - 1));
//				System.out.println(redLinJ.get(redLinJ.size() - 1));
				boolean findNext = true;
				boolean write = true;
				int maxHei = redJ;
				int minHei = redJ;
				int newI = 0, newJ = 0;
				int oldI = -1, oldJ = -1;
				
				//int pocitam = 0;
				
				while ( (redI < ip.getWidth()) && (findNext) ){
					
/*					pocitam++;
					if (pocitam > 600)
						System.out.println("ZASEKAVAM SA??separ2");*/
					
					findNext = false;
					write = true;
					if ((ip.getPixel(redI+1, redJ+1) == color) && (!((redI+1 == oldI) && (redJ+1 == oldJ))) ){
						newI = redI+1;
						newJ = redJ+1;
						findNext = true;
					} else if ((ip.getPixel(redI+1, redJ) == color) && (!((redI+1 == oldI) && (redJ == oldJ))) ){
						newI = redI+1;
						newJ = redJ;
						findNext = true;
					} else if ((ip.getPixel(redI+1, redJ-1) == color) && (!((redI+1 == oldI) && (redJ-1 == oldJ))) ){
						newI = redI+1;
						newJ = redJ-1;
						findNext = true;
					} else if ((ip.getPixel(redI, redJ+1) == color) && (!((redI == oldI) && (redJ+1 == oldJ))) ) {//nechcem zapisovat
						write = false;
						findNext = true;
						newI = redI;
						newJ = redJ+1;
					} else if ((ip.getPixel(redI, redJ-1) == color) && (!((redI == oldI) && (redJ-1 == oldJ))) ){//nechcem zapisovat
						newI = redI;
						newJ = redJ-1;
						write = false;
						findNext = true;
					} 
					oldI = redI;
					oldJ = redJ;
					if ((findNext) && (write)) {
						redLinI.add(newI);
						redLinJ.add(newJ);
						//System.out.println(redLinI.get(redLinI.size() - 1));
						//System.out.println(redLinJ.get(redLinJ.size() - 1));
						if (redJ > maxHei )
							maxHei = redJ;
						if (redJ < minHei )
							minHei = redJ;
					}
					redI = newI;
					redJ = newJ;
					//System.out.println("oldI:" +oldI);
					//System.out.println("oldJ:" +oldJ);
					//System.out.println("redI:" +redI);
					//System.out.println("j:" +j);
					//System.out.println("findNext:" +findNext);
					//System.out.println("write:" +write);
				}
				
				if (redI < ip.getWidth()) {
					for (int k = redI; k < ip.getWidth(); k++) {
						redLinI.add(k);
						redLinJ.add(redJ);
					}
				}
				
				redLinesI.add(redLinI);
				redLinesJ.add(redLinJ);
				maxHeight.add(maxHei);
				minHeight.add(minHei);
//				System.out.println();
			}
			
			j++;
		}
		
/*		imp2 = NewImage.createRGBImage ("Line Segmentation", ip.getWidth(), ip.getHeight(), 1, NewImage.FILL_WHITE);		
		nip = imp2.getProcessor();	
		
		for (int k = 0; k < redLinesI.size(); k++) {
			for (int index = 0; index < redLinesI.get(k).size(); index++) {
				
		
						nip.putPixel((Integer)(redLinesI.get(k).get(index)), (Integer)(redLinesJ.get(k).get(index)), color);
				
				
			}
		}
		
		if (draw) {	
			mainWindow.intFrame[FileChooser.number] = new internalFrame("Line Segmentation", imp2, FileChooser.number, numberResult);
			try {
				mainWindow.intFrame[FileChooser.number].setSelected(true);
			} catch(Exception e){
				System.out.println("Chyba");
			}	
			++FileChooser.number;
		}*/
		
		int length = 0;
		for (int k = 0; k < maxHeight.size(); k++) {
			if (k != maxHeight.size() - 1)
				length += ( (Integer)(maxHeight.get(k)) - (Integer)(minHeight.get(k+1)) ) /2;
		}
		
		imp2 = NewImage.createRGBImage ("Line Segmentation", ip.getWidth(), ip.getHeight()+length, 1, NewImage.FILL_WHITE);		
		nip = imp2.getProcessor();	
		nip.setColor(color);
		
		int kresliJ = 0;
		
		for (int k = 0; k < redLinesI.size(); k++) {
			for (int index = 0; index < redLinesI.get(k).size(); index++) {
				for (j = (Integer)(minHeight.get(k))+1; j < (Integer)(maxHeight.get(k)); j++) {
					int lastLine;
					if (k == 0)
						lastLine = 0;
					else 
						lastLine = (Integer)(redLinesJ.get(k-1).get(index));
					if ((j < (Integer)(redLinesJ.get(k).get(index)) ) && (j > lastLine ) && (nipOtsu.getPixelValue(index, j) == 0) )
						nip.putPixelValue(index, j + kresliJ, nipOtsu.getPixelValue(index, j));
				}
				
			}
			//nip.drawLine(0, (Integer)(maxHeight.get(k)) +kresliJ, nip.getWidth(), (Integer)(maxHeight.get(k))+ kresliJ);
			if (k == redLinesI.size() - 1)
				kresliJ += (Integer)(maxHeight.get(k));
			else
				kresliJ +=  ( (Integer)(maxHeight.get(k)) - (Integer)(minHeight.get(k+1)) ) /2;
		}
		
		kresliJ = 0;
		for (int k = 0; k < redLinesI.size(); k++) {
			nip.drawLine(0, (Integer)(maxHeight.get(k)) +kresliJ, nip.getWidth(), (Integer)(maxHeight.get(k))+ kresliJ);
			if (k == redLinesI.size() - 1)
				kresliJ += (Integer)(maxHeight.get(k));
			else
				kresliJ +=  ( (Integer)(maxHeight.get(k)) - (Integer)(minHeight.get(k+1)) ) /2;
		}		
		
/*		while (j < ip.getHeight()) {
			i = 0;
			while ((j < ip.getHeight()) && (ip.getPixel(i, j) != color)) 
				j++;
			p = 0;
			max = 0;
			white_i.add(p, i);
			white_j.add(p, j);

			p++;
			ip.putPixelValue(i, j, 255);
			nipnew.putPixel(i, j, color2);
			if (j > max) max = j;
					while ((i != ip.getWidth() -1) && (p < 2*ip.getWidth())){
						if (ip.getPixel(i+1, j) == color) {
							i++;
						} else if (ip.getPixel(i+1, j-1) == color) {
							i++;
							j--;
						} else if (ip.getPixel(i+1, j+1) == color) {
							i++;
							j++;
						} else if (ip.getPixel(i, j-1) == color) j--;
						else if (ip.getPixel(i, j+1) == color) j++;
						if (j > max) max = j;
						white_i.add(p, i);
						white_j.add(p, j);
						ip.putPixelValue(i, j, 255);
						nipnew.putPixel(i, j, color2);
						p++;
					}
					
					
					for (int k = 0; k < ip.getWidth(); k++) {
						for (int h = oldMax; h <= max -1; h++) {
							if (nipOtsu.getPixelValue(k, h) == 0) {
								sepI.add(k);
								sepJ.add(h - oldMax + height);
								nipOtsu.putPixelValue(k, h, 255);
							}
						}
					}
					
					height = height + max - oldMax;
					height = height + 1;// + 5 + 1 + 5; //medzera, cervena, medzera
					redJ.add(height);// - 5);

					white_i.clear();
					white_j.clear();
					oldMax = max;
				//} 
		}*/	
		
/*		while (j < ip.getHeight()) {
			i = 0;
			while ((j < ip.getHeight()) && (ip.getPixel(i, j) != color)) 
				j++;
			p = 0;
			max = 0;
			white_i.add(p, i);
			white_j.add(p, j);
				//	System.out.println("white_i "+white_i.get(p));
				//	System.out.println("white_j "+white_j.get(p));
			p++;
			ip.putPixelValue(i, j, 255);
			nipnew.putPixel(i, j, color2);
			if (j > max) max = j;
					while ((i != ip.getWidth() -1) && (p < 2*ip.getWidth())){
						if (ip.getPixel(i+1, j) == color) {
							i++;
						} else if (ip.getPixel(i+1, j-1) == color) {
							i++;
							j--;
						} else if (ip.getPixel(i+1, j+1) == color) {
							i++;
							j++;
						} else if (ip.getPixel(i, j-1) == color) j--;
						else if (ip.getPixel(i, j+1) == color) j++;
						if (j > max) max = j;
						white_i.add(p, i);
						white_j.add(p, j);
						ip.putPixelValue(i, j, 255);
						nipnew.putPixel(i, j, color2);
						p++;
					}
					
					
					for (int k = 0; k < ip.getWidth(); k++) {
						for (int h = oldMax; h <= max -1; h++) {
							if (nipOtsu.getPixelValue(k, h) == 0) {
								//System.out.println("oldmax "+oldMax);
								//System.out.println("max "+max);
								//nip.putPixelValue(k, h - oldMax, nipOtsu.getPixelValue(k, h));
								sepI.add(k);
								sepJ.add(h - oldMax + height);
								nipOtsu.putPixelValue(k, h, 255);
							}
						}
					}
					
					height = height + max - oldMax;
					height = height + 1;// + 5 + 1 + 5; //medzera, cervena, medzera
					redJ.add(height);// - 5);

					imp2 = NewImage.createRGBImage ("Line Segmentation", ip.getWidth(), max- oldMax, 1, NewImage.FILL_WHITE);		
					nip = imp2.getProcessor();	
					
					for (int k = 0; k < nip.getWidth(); k++) {
						for (int h = oldMax; h <= max; h++) {
							if (nipOtsu.getPixelValue(k, h) != 255) {
								nip.putPixelValue(k, h - oldMax, nipOtsu.getPixelValue(k, h));
								nipOtsu.putPixelValue(k, h, 255);
							}
						}
					}
										
						
						mainWindow.intFrame[FileChooser.number] = new internalFrame(imp2.getTitle()+ " - Line Segmentation", imp2, FileChooser.number);
						try {
							mainWindow.intFrame[FileChooser.number].setSelected(true);
						} catch(Exception e){
							System.out.println("Chyba");
						}	
						++FileChooser.number;
					white_i.clear();
					white_j.clear();
					oldMax = max;
				//} 
		}*/		
		
		//redJ.add(height - 1);// - 5);
		
/*		imp2 = NewImage.createRGBImage ("Line Segmentation", ip.getWidth(), height, 1, NewImage.FILL_WHITE);		
		nip = imp2.getProcessor();	
		
		for (int k = 0; k < sepI.size(); k++) {
			//System.out.println("(Integer)(sepI.get(k)) "+(Integer)(sepI.get(k)));
			//System.out.println("(Integer)(sepJ.get(k)) "+(Integer)(sepJ.get(k)));
			nip.putPixelValue((Integer)(sepI.get(k)), (Integer)(sepJ.get(k)), 0);
		}
		color = ((Color.red.getRed() & 0xff) << 16) + ((0 & 0xff) << 8) + (0 & 0xff);//red color
		nip.setColor(color);*/
		
		
		//prvy ani posledny riadok nebudem ratat!!!!
		//OPRAVENE
		//ArrayList maxHeight = new ArrayList();
		
/*		int k = 0;
		int index = 0;
		
		while ((k < nip.getHeight()-1) && (nip.getPixelValue(index, k)!=0)) {
			index = 0;
			while ((index < nip.getWidth()-1) && (nip.getPixelValue(index, k)!=0)) {
				index++;
			}
			if (nip.getPixelValue(index, k)!=0)
				k++;
		}
		
		//vyska celeho dokumentu od prveho cierneho bodu po poslednu cervenu ciaru
		double heightText = (Integer)(maxHeight.get(maxHeight.size()-1)) - k;
		System.out.println("HEIGHTTEXT "+heightText);
		
		//podelim heightText poctom riadkov
		double heightTextLine = heightText / (maxHeight.size() -1);
		
		Result.setHeightTextLine(heightTextLine, numberResult);*/
		
		double[] resultDiffLines = new double[maxHeight.size() -1];
		
		for (int k = 0; k < maxHeight.size()-1; k++) {
			resultDiffLines[k] = (Integer)(maxHeight.get(k+1)) - (Integer)(maxHeight.get(k));
//			System.out.println("DIFF LINES[i] "+resultDiffLines[k]);
		}
		
/*		for (int k = 0; k < redJ.size(); k++) {
			nip.drawLine(0, (Integer)(redJ.get(k)), nip.getWidth(), (Integer)(redJ.get(k)));
			if ( (k != 0) && (k != redJ.size() -1) )
				resultDiffLines[k-1] = (Integer)(redJ.get(k)) - (Integer)(redJ.get(k-1));
		}*/		
		
		//pixle TODO zmenit na percentualnost
		Result.setDiffLines(resultDiffLines, numberResult);

		if (draw) {	
			mainWindow.intFrameArrayList.add(new internalFrame("Line Segmentation", imp2, FileChooser.number, numberResult, 1, true));
			try {
				//mainWindow.intFrame[FileChooser.number].setSelected(true);
				((internalFrame)(mainWindow.intFrameArrayList.get(FileChooser.number))).setSelected(setSelected);
			} catch(Exception e){
				System.out.println("Chyba");
			}	
			++FileChooser.number;
		}
		
/*		mainWindow.intFrame[FileChooser.number] = new internalFrame(impnew.getTitle()+ " - Line Segmentation", impnew, FileChooser.number, numberResult);
		try {
			mainWindow.intFrame[FileChooser.number].setSelected(true);
		} catch(Exception e){
			System.out.println("Chyba");
		}	
		++FileChooser.number;*/
		
		///RESULT////////////////////////////
		color = ((Color.red.getRed() & 0xff) << 16) + ((0 & 0xff) << 8) + (0 & 0xff); //red color
		
		ArrayList redJnew = new ArrayList();
		
			redJnew .add(0);
			for (j = 0; j < nip.getHeight(); j++) {			
				if (nip.getPixel(0, j) == color) {
					redJnew .add(j);
				}
			}
//////////////OPRAVENE
/////////DENSITY BEGIN ///////////////
		double[] density = new double[redJnew.size()-1];
		int numberPixels = 0;

		for (i = 0; i < redJnew.size()-1; i++) {
			numberPixels = 0;
			for (j = 0; j < nip.getWidth(); j++) {
				for (int k = (Integer)(redJnew.get(i))+1; k < (Integer)(redJnew.get(i+1))-1; k++) {
					if (nip.getPixelValue(j, k) == 0)
						numberPixels++;
				}
			}
			density[i] = numberPixels;
//			System.out.println("density[i] "+density[i]);
		}		
		
		Result.setDensityHandwr(density, numberResult);
///////DENSITY END/////////////////////////
			
/*		ArrayList<ArrayList> density = new ArrayList<ArrayList>();
		for (i = 0; i < redLinesJ.size(); i++) {
			ArrayList d = new ArrayList();	
			for (j = 0; j < nip.getWidth(); j++) {
				int l = 0;
				if (i != 0)
					l = (Integer)(redLinesJ.get(i-1));
				count = 0;
				for (int k = l; k < (Integer)(redLinesJ.get(i)); k++) {
					if (nip.getPixelValue(j, k) == 0)
						count++;
				}
				if (count != 0)
					d.add(count);
			}
			density.add(d);
		}
		
		double[] densityResult = new double[density.size()];
		for (i = 0; i < density.size(); i++) {
			double sum = 0;
			for (j = 0; j < density.get(i).size(); j++) {
				sum = sum + (Integer)(density.get(i).get(j));
			}
			sum = sum / density.get(i).size();
			densityResult[i] = sum;
		}*/
		
		//pixle TODO zmenit na percentualnost
	//	Result.setDensityHandwr(densityResult, numberResult);

		
	}
	
	protected void finalize() throws Throwable {
	    try {
	        //close();        // close open files
	    } finally {
	        super.finalize();
	        System.out.println("separation has been finalized.");
	    }
	}	
	
	
	public ImagePlus getImg(){
		return imp2;
	}
	
	public ImageProcessor getIp(){
		return nip;
	}	
	
}