package eu.dnetlib.enabling.graph.utils;

import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.imageio.ImageIO;

import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.jgraph.JGraph;
import org.jgraph.graph.GraphLayoutCache;
import org.jgrapht.ext.JGraphModelAdapter;
import org.jgrapht.graph.DefaultListenableGraph;

import com.jgraph.io.svg.SVGGraphWriter;
import com.jgraph.layout.JGraphFacade;
import com.jgraph.layout.JGraphLayout;

import eu.dnetlib.enabling.graph.objects.DnetVertex;

public class DnetGraph {	
	
	private static final Color DEFAULT_BG_COLOR = Color.decode("#FAFBFF");
	private static final int WIDTH = 4000;
	private static final int HEIGHT = 4000;
	private JGraphLayout layout;
	private JGraph jgraph;
	private JGraphModelAdapter<DnetVertex, DnetEdge> jgAdapter;
	private DefaultListenableGraph<DnetVertex, DnetEdge> grapht;
	
	private static final Log log = LogFactory.getLog(DnetGraph.class); // NOPMD by marko on 11/24/08 5:02 PM
	
	public DnetGraph(DefaultListenableGraph<DnetVertex, DnetEdge> gt, JGraphLayout layout) {
		this.jgAdapter = new JGraphModelAdapter<DnetVertex, DnetEdge>(gt);
		this.jgraph = new JGraph(jgAdapter);
		this.grapht = gt;
		this.layout = layout;
		jgraph.setSize(DnetGraph.WIDTH, DnetGraph.HEIGHT);
		jgraph.setBackground(DnetGraph.DEFAULT_BG_COLOR);
	}

	public void addSimpleObject(DnetVertex vertex) {
		grapht.addVertex(vertex);
		vertex.formatVertex(jgAdapter);
	}
	
	public void addRelationSimple(DnetVertex v1, DnetVertex v2, String message) {
		log.info(v1.getId() + " -> " + v2.getId());
		
		addEdge(v1, v2, new DnetEdge(message));
	}

/*	public void addRelationAdvanced(DnetGraphObject rel, DnetGraphObject objFst, DnetGraphObject objSnd) {
		addSimpleObject(rel);
		addEdge(DnetVertex.getInstance(objFst), DnetVertex.getInstance(rel), new DnetEdge("First"));
		addEdge(DnetVertex.getInstance(objSnd), DnetVertex.getInstance(rel), new DnetEdge("Second"));
	}
*/
	
	private void addEdge(DnetVertex from, DnetVertex to, DnetEdge edge) {
		grapht.addEdge(from, to, edge);
		edge.formatEdge(jgAdapter);
	}
	
	
	private void applyTemplate() {
		if (layout != null) {
			JGraphFacade facade = new JGraphFacade(jgraph);
			layout.run(facade);
			jgraph.getGraphLayoutCache().edit(facade.createNestedMap(true, true));	
		}
	}
	
	public void asImagePNG(OutputStream out) throws IOException {
		applyTemplate();
	
		BufferedImage imgOut = jgraph.getImage(DEFAULT_BG_COLOR, 1);
		
		if (imgOut != null) {
			ImageIO.write(imgOut, "png", out);
		} else {
			InputStream input = getClass().getResourceAsStream("/eu/dnetlib/enabling/graph/utils/img/error.png");
			IOUtils.copy(input, out);
		}
	}
	
	
	public void asImageSVG(OutputStream out) {
		applyTemplate();
		SVGGraphWriter writer = new DnetSVGGraphWriter();
		GraphLayoutCache cache = jgraph.getGraphLayoutCache();
		writer.write(new BufferedOutputStream(out), null, cache, 35);
	}

}
