/*******************************************************************************
 * Copyright (C) 2017 Philipp Spohr
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 ******************************************************************************/
package de.hhu.ba.yoshikoWrapper.graphModel;

import java.awt.Image;
import java.util.ArrayList;
import java.util.List;

import javax.swing.ImageIcon;
import javax.swing.JLabel;
import javax.swing.SwingUtilities;

import org.cytoscape.model.CyEdge;
import org.cytoscape.model.CyNetwork;
import org.cytoscape.model.CyNode;
import org.cytoscape.model.CyRow;
import org.cytoscape.model.subnetwork.CyRootNetwork;
import org.cytoscape.model.subnetwork.CySubNetwork;
import org.cytoscape.view.layout.CyLayoutAlgorithm;
import org.cytoscape.view.model.CyNetworkView;
import org.cytoscape.view.presentation.RenderingEngine;
import org.cytoscape.view.vizmap.VisualStyle;
import org.cytoscape.work.Task;
import org.cytoscape.work.TaskIterator;
import org.cytoscape.work.TaskMonitor;

import de.hhu.ba.yoshikoWrapper.core.CyCore;
import de.hhu.ba.yoshikoWrapper.core.LocalizationManager;

import static org.cytoscape.view.presentation.property.BasicVisualLexicon.NETWORK_HEIGHT;
import static org.cytoscape.view.presentation.property.BasicVisualLexicon.NETWORK_WIDTH;

public class YoshikoCluster {
	
	
	private final long id;
	
	private ArrayList<CyNode> nodes;
	private CySubNetwork net;
		
	//SYMBOLIC LINKS
	private final CyNetwork originalGraph;

	
	
	public YoshikoCluster(long id, CyNetwork originalGraph) {
		this.id = id;
		this.originalGraph = originalGraph;
		this.nodes = new ArrayList<CyNode>();		
	}
	
	private void createSubNetwork() {
		
		CyRootNetwork originalGraphAsRoot = CyCore.rootNetworkManager.getRootNetwork(originalGraph);

		//Create nested graph and cluster subnet
		ArrayList<CyEdge> inducedEdges = new ArrayList<CyEdge>();
		for (CyNode n: nodes) {
			//Sadly Cytoscape doesnt provide a comfort function here
			List<CyEdge> adjacentEdges = originalGraph.getAdjacentEdgeList(n, CyEdge.Type.ANY);
			for (CyEdge e: adjacentEdges) {
				if (nodes.contains(e.getSource()) && nodes.contains(e.getTarget())) {
					inducedEdges.add(e);
				}
			}
		}
		CySubNetwork subnet = originalGraphAsRoot.addSubNetwork(nodes ,inducedEdges);

		subnet.getRow(subnet).set(CyNetwork.NAME, LocalizationManager.get("cluster")+" "+(id+1));
		
		net = subnet; //Save for further reference		
	}
	
	public void select() {
		List<CyRow> allRows = originalGraph.getDefaultNodeTable().getAllRows();
		for (CyRow r: allRows) {
			r.set("selected", false);
		}
		//Select nodes corresponding to the cluster
		for (CyNode n : nodes) {
			originalGraph.getRow(n).set("selected", true);
		}
	}
	

	public void generateImage(JLabel label, int width, int height) {
		if (net == null) {
			createSubNetwork();
		}
		CyNetworkView view = CyCore.networkViewFactory.createNetworkView(net);
		
		//layout cluster
		CyLayoutAlgorithm layout = CyCore.layoutAlgorithmManager.getDefaultLayout();
		TaskIterator createLayout = layout.createTaskIterator(
			view, 
			layout.getDefaultLayoutContext(), 
			CyLayoutAlgorithm.ALL_NODE_VIEWS,
			null
		);
		
		createLayout.append(
			new Task() {

				@Override
				public void run(TaskMonitor taskMonitor) throws Exception {
					taskMonitor.setStatusMessage("Generating cluster view for C:"+id);
					
					VisualStyle vs= CyCore.visualStyleFactory.createVisualStyle(CyCore.visualMappingManager.getCurrentVisualStyle());
					CyCore.visualMappingManager.setVisualStyle(vs, view);
					vs.apply(view);

					view.setVisualProperty(NETWORK_WIDTH, new Double(width));
					view.setVisualProperty(NETWORK_HEIGHT, new Double(height));
					view.fitContent();
					view.updateView();
										
					RenderingEngine<CyNetwork> renderingEngine = CyCore.renderingEngineFactory.createRenderingEngine(label, view);
					SwingUtilities.invokeLater(new Runnable() {

						@Override
						public void run() {
							Image img = renderingEngine.createImage(width,height);
							label.setIcon(new ImageIcon(img));
							
							renderingEngine.dispose();
							view.dispose();
						}
						
					});

					
				}

				@Override
				public void cancel() {
					// TODO Auto-generated method stub
				}
				
			}
	    );
		
		CyCore.dialogTaskManager.execute(
				createLayout
		);
		

	}

	public int getSize() {
		return nodes.size();
	}

	public long getID() {
		return id;
	}

	public CySubNetwork getSubNetwork() {
		if (net == null) {
			createSubNetwork();
		}
		return net;
	}

	public void addNode(CyNode node) {
		nodes.add(node);
	}

	public String getNodeName(CyNode n) {
		return originalGraph.getRow(n).get("name", String.class);
	}



}