package segmentation;

import java.awt.image.BufferedImage;
import java.util.Random;
import java.util.Stack;

import preprocessing.Util;


public class Labels {
	
	private int width;
	private int height;
	private int number_of_regions;
	private int[] lab;
	
	public Labels (int width, int height)
	{
		this.width = width;
		this.height = height;
		this.lab = new int[width*height]; 
	}
	
	public int getValue (int pos) {
		return lab[pos];
	}
	
	public int getNumberOfRegions () {
		return number_of_regions;
	}
	
	public int getWidth () {
		return this.width;
	}
	
	public int getHeight () {
		return this.height;
	}
	
	public void setNumberOfRegions (int number_of_regions) {
		this.number_of_regions = number_of_regions;
	}	
	
	public void print (int size) {
		for (int i = 0; i < size; i++) {
		   System.out.println("pos : " 	+ i + ", value : " + this.lab[i]);
		}  
	}
	
	private void label_area (int[] inarray, int width, int label_num, int value, Stack<Integer> p)
	{
	    int i;
	    
	    while (!p.empty()) {
	    	
	        int offset = p.pop();
	        
	        lab[offset]=label_num;
	        if (inarray[offset - width] == value && lab[offset - this.width]==0) {
	        	p.push(offset - width);
	        }
	        if (inarray[offset + width] == value && lab[offset + this.width]==0) {
	        	p.push(offset + width);
	        }

	        i = offset + 1;
	        
	        while (inarray[i] == value) {
	            lab[i] = label_num;
	            if ( (inarray[i - width] == value) && (lab[i - width] == 0) && (inarray[i - width - 1] != value) ) {
	            	p.push(i - width);
	            }
	            if ( (inarray[i + width] == value) && (lab[i + width] == 0) && (inarray[i + width - 1] != value) ) {
	            	p.push(i + width);
	            }
	            i++;
	        }

	        i = offset - 1;
	        while (inarray[i] == value) {
	            lab[i] = label_num;
	            if (inarray[i - width] == value && lab[i - width] == 0 && inarray[i - width + 1] != value) {
	            	p.push(i - width);
	            }
	            if (inarray[i + width] == value && lab[i + width] == 0 && inarray[i + width + 1] != value) {
	            	p.push(i + width);
	            }
	            i--;
	        }
	    }
	}
	

	
	public int create_labels_from_image (int w, int h, int[] image) {
		
        int next_label = 1;
		
        int size = w * (h - 1) - 1;
        
    	Stack<Integer> p =  new Stack<Integer>();
        
    	/*setting the image edges as background regions*/
        for (int i = 0; i < w; i++) {
        	image[i] = Segmentation.BACKGROUND; 
        }
        for (int i = w*(h-1); i < (w*h); i++) {
        	image[i] = Segmentation.BACKGROUND;
        }
                    
        for(int i = 0; i < h; i++) {
        	image[i * w] = image[(i+1) * w - 1] = Segmentation.BACKGROUND;
        }

        for(int i = w + 1; i < size; i++) {
            if ( (image[i] != Segmentation.BACKGROUND) && (lab[i] == 0) ) {
            	 p.push(i);
                 label_area(image, w, next_label, image[i], p);
                 next_label++;
            }
        }
        return next_label;
	}
	
	public BufferedImage Get_Image_From_Labels ()
	{
		int[] r = new int[number_of_regions];
		int[] g = new int[number_of_regions];
		int[] b = new int[number_of_regions];
		
		r[0] = g[0] = b[0] = 0;
	    BufferedImage outimg = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
	    
	    int size = width * height;
	    
	 	int[] out = new int[width*height];
	    
	    Random ran = new Random (System.currentTimeMillis());
	    
	    for(int i = 1; i < number_of_regions; i++) {

	    	r[i] = 55 + ran.nextInt(200);
	    	g[i] = 55 + ran.nextInt(200);
	    	b[i] = 55 + ran.nextInt(200);
	    }
	    
	    if (number_of_regions >= 2) {
	    	r[1] = b[1] = 0;
	    	g[1] = 255;
	    }
	    if (number_of_regions >= 3) {
	    	r[2] = 255;
	    	g[2] = b[2] = 0;
	    }
	    if (number_of_regions >= 4) {
	    	b[3] = 0;
	    	r[3] = g[3] = 255;
	    }
	    
	    int i; 
	    for(i = 0; i < size; i++) {
	    	int v = lab[i];
	      
	        int p0 = b[v];
	        int p1 = g[v];
	        int p2 = r[v];
	        int p =  ( (p0) | (p1 << 8) | (p2 << 16) | (255 << 24) );
	        
	        out[i] = p;
	    }
	    int startX = 0; int startY = 0;
	  
		outimg.setRGB(startX, startY, width, height, out, 0, width);
	    return outimg;
	}
	
	
	
	
	
	
 }
