package es.geograma.render;

import java.awt.AlphaComposite;
import java.awt.Color;
import java.awt.Component;
import java.awt.Composite;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GraphicsEnvironment;
import java.awt.Image;
import java.awt.Panel;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.awt.image.FilteredImageSource;
import java.awt.image.ImageFilter;
import java.awt.image.ImageProducer;
import java.awt.image.RGBImageFilter;
import java.awt.image.RenderedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;

import javax.imageio.ImageIO;

import org.apache.log4j.Logger;

import es.prodevelop.gvsig.mobile.fmap.MapContext;
import es.prodevelop.gvsig.mobile.fmap.driver.FMapDriverException;
import es.prodevelop.gvsig.mobile.fmap.driver.raster.ecw.EcwReader;
import es.prodevelop.gvsig.mobile.fmap.layer.FLayer;
import es.prodevelop.gvsig.mobile.fmap.util.Defaults;
import es.prodevelop.gvsig.mobile.fmap.util.ResourceReader;
import es.prodevelop.gvsig.mobile.fmap.util.Utils;
import es.prodevelop.gvsig.mobile.fmap.util.cancel.Cancellable;
import es.prodevelop.gvsig.mobile.fmap.viewport.ViewPort;
import es.prodevelop.gvsig.mobile.gui.canvas.MapControl;

public class Render 
{
	private Graphics2D g = null;
	private ViewPort vp = null;
	public static Logger logger = Logger.getLogger(Render.class);
	private ArrayList imageLayers = new ArrayList();
	private int numLayersPainted = 0;
	private int indices[] = null;
	private MapControl mapControl = null;
	//private Image imageLayer = null;
	
	public Render(Graphics2D g,ViewPort vp,MapControl mapControl)
	{
		this.g = g;
		this.vp = vp;
		this.mapControl = mapControl;
	//	imageLayer = ResourceReader.getResourceImage(ResourceReader.IMG_SKIN_PATH, "transparencia.png");
	}
	
	public void draw(FLayer layer)
	{
		try
		{
			layer.draw(this.g, this.vp);
			
		}catch(FMapDriverException e)
		{
			logger.error("While drawing layer: " + layer.getName());
            logger.error("Error message: " + e.getMessage());
		}
	}
	
	public void draw(FLayer layers[],Cancellable canc)
	{
		int size = layers.length;
		indices = new int[size];
		
		for (int i = 0; i < size; i++) 
		{
            FLayer lyr = layers[i];
            indices[i] = 0;
            if (canc.isCanceled()) {
                return;
            }
            // Creamos una imagen vacía
            //Image imageLyr = Utils.createBufferedImage(this.g.getClipBounds().width,this.g.getClipBounds().height);
            BufferedImage imageLyr = Utils.createBufferedImage(this.g.getClipBounds().width,this.g.getClipBounds().height);
            /*
             Rectangle rectangle = new Rectangle(0, 0,this.g.getClipBounds().width,
            		this.g.getClipBounds().height);
            BufferedImage imageLyr = null;
            */
            try{
	            //Robot robot = new Robot();
	            //imageLyr = robot.createScreenCapture(rectangle);
            
	            // La rellenamos con el color qeu posteriormente vamos a poner como transparente
	            Graphics2D gg =(Graphics2D) imageLyr.getGraphics();
	            gg.drawImage(mapControl.imageLayerTransparent, 0, 0, null);
	            
	            // La añadimos a la cola
	            imageLayers.add(imageLyr);
	            LayerThread layerThread = new LayerThread(this,lyr,i,(Graphics2D)gg,vp);
	            layerThread.start();
            
            }catch(Exception ops)
            {
            	
            }

            
        }
		
		// Esperamos 30 segundos como mucho
		/*
		long t1 = System.currentTimeMillis();
		while (numLayersPainted<size)
		{
			long t2 =  System.currentTimeMillis();
			if (((t2 - t1)/ 1000)>30)
			{
				forzeUpdate();
				break;
			}
		}
		*/
	}
	private AlphaComposite makeComposite(float alpha) {
	    int type = AlphaComposite.SRC_OVER;
	    return(AlphaComposite.getInstance(type, alpha));
	  }

	
	public void update(int order)
	{
		indices[order] = 1;
		numLayersPainted += 1;
		
		for(int i=0;i<indices.length;i++)
		{
			if(indices[i]==1)
			{
				// Le damos transparencia
				long t1 = System.currentTimeMillis();
				Image aux = Transparency.makeColorTransparent((Image)imageLayers.get(i), new Color(1,1,255));
				long t2 = System.currentTimeMillis();
				Render.logger.error("Transparency: " + (t2 - t1) + " mseg.");
				this.g.drawImage(aux, 0, 0, null);
				
			}
		}
		
		//this.mapControl.repaint();
		//this.mapControl.setProcessing(false);
		if(numLayersPainted<indices.length)
			this.mapControl.setProcessing(true,false, this.g);
			//this.mapControl.setProcessing(false);
			//this.mapControl.dontRedraw = true;
		else
		{
			//mapControl.hasFinished = true;
			this.mapControl.setProcessing(false,false, this.g);
			//this.mapControl.dontRedraw = true;
			//this.mapControl.setProcessing(true);
		}
		//this.mapControl.refresh(false);	
		//this.mapControl.redraw(true);
		//long t1 = System.currentTimeMillis();
		//this.mapControl.repaint();
		this.mapControl.repaint();
		
		//long t2 = System.currentTimeMillis();
		//Render.logger.error("repaint: " + (t2 - t1) + " mseg.");
	}
	
}

class LayerThread extends Thread
{
	private Render render;
	private int order;
	private FLayer layer;
	private Graphics2D g;
	private ViewPort vp;
	
	public LayerThread(Render render,FLayer layer, int order, Graphics2D g, ViewPort vp)
	{
		this.render = render;
		this.order = order;
		this.layer = layer;
		this.g = g;
		this.vp = vp;
	}
	public void run()
	{
		try{
			long t1 = System.currentTimeMillis();
			this.layer.draw(this.g,this.vp);
			long t2 = System.currentTimeMillis();
			Render.logger.error("Render("+this.layer.getName()+") tiempo(capa): " + (t2 - t1) + " mseg.");
			//this.g.finalize();
			render.update(this.order);
			long t3 = System.currentTimeMillis();
			Render.logger.error("Render("+this.layer.getName()+") tiempo(mapa): " + (t3 - t1) + " mseg.");
		}catch(FMapDriverException e)
		{
			Render.logger.error("While drawing layer: " + layer.getName());
			Render.logger.error("Error message: " + e.getMessage());
		}
	}
}

class Transparency {
	  public static Image makeColorTransparent
	    (Image im, final Color color) {
	    ImageFilter filter = new RGBImageFilter() {
	      // the color we are looking for... Alpha bits are set to opaque
	      public int markerRGB = color.getRGB() | 0xFF000000;

	      public final int filterRGB(int x, int y, int rgb) {
	        if ( ( rgb | 0xFF000000 ) == markerRGB ) {
	          // Mark the alpha bits as zero - transparent
	          return 0x00FFFFFF & rgb;
	          }
	        else {
	          // nothing to do
	          return rgb;
	          }
	        }
	      }; 

	    ImageProducer ip = new FilteredImageSource(im.getSource(), filter);
	    return Toolkit.getDefaultToolkit().createImage(ip);
	    }
	}