package de.visone.crawl;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import atomicwheel.Attribute;
import atomicwheel.AttributeManager;
import atomicwheel.Edge;
import atomicwheel.Graph;
import atomicwheel.Node;
import de.visone.base.Network;
import de.visone.crawl.out.Content;
import de.visone.crawl.sys.Link;
import de.visone.ext.nlp.TextNetworkUtil;

/**
 * Creates a network from the pages crawled by the crawler.
 * 
 * @author matthias
 */
public class CrawlAlgorithm {
	private final Graph network;
	private final Map<String, Node> nodeMap;
	private final Attribute<Node, String> urlAttribute;
	private final Attribute<Edge, String> linkText;
	private final Attribute<Node, String> pageText;
	private final Attribute<Edge, Boolean> confirmation;

	/**
	 * Creates a new crawler network creation algorithm.
	 * 
	 * @param doText
	 *            true to create an attribute containing the page text
	 * @param net
	 *            the {@link Network} into which the graph is written
	 */
	public CrawlAlgorithm(final boolean doText, final Graph net) {
		network = net;

		nodeMap = new HashMap<String, Node>();
		final AttributeManager<Node> nodeManager = network
				.getNodeAttributeManager();
		urlAttribute = nodeManager.createAttribute(TextNetworkUtil.URL,
				String.class);
		final AttributeManager<Edge> edgeManager = network
				.getEdgeAttributeManager();
		linkText = edgeManager.createAttribute(TextNetworkUtil.LINKTEXT,
				String.class);
		if (doText)
			pageText = nodeManager.createAttribute("text", String.class);
		else
			pageText = null;
		confirmation = network.getEdgeAttributeManager().createAttribute(
				TextNetworkUtil.CONFIRMATION, Boolean.class);
	}

	/**
	 * Processes the given {@link Content} object containing the link structure
	 * and, optionally, the text of the most recently crawled page.
	 * 
	 * @param content
	 *            page content
	 */
	public void processContents(final Content content) {
		final Node source = createNode(content.getURL().toString());
		for (final Link link : content.getAcceptedLinks()) {
			final Node target = createNode(link.getUrl().toString());
			createEdge(source, target, link.getText(), true);
		}
		for (final Link link : content.getOtherLinks()) {
			final Node target = createNode(link.getUrl().toString());
			createEdge(source, target, link.getText(), false);
		}
		if (pageText != null)
			pageText.set(source, content.getText());
	}

	protected Node createNode(final String url) {
		if (nodeMap.containsKey(url))
			return nodeMap.get(url);
		final Node node = new Node();
		network.add(node);

		nodeMap.put(url, node);
		urlAttribute.set(node, url);
		return node;
	}

	protected void createEdge(final Node source, final Node target,
			final List<String> texts, final boolean confirmed) {
		for (final String s : texts) {
			final Edge edge = new Edge(source, target, true);
			network.add(edge);
			linkText.set(edge, s);
			confirmation.set(edge, confirmed);
		}
	}
}
