package de.visone.crawl.gui;

import java.io.IOException;

import transportgraph.TransportGraph;
import atomicwheel.Graph;
import atomicwheel.why.TransportGraphConverter;
import de.visone.base.Mediator;
import de.visone.crawl.CrawlAlgorithm;
import de.visone.crawl.Settings;
import de.visone.crawl.out.Content;
import de.visone.crawl.out.CrawlListener;
import de.visone.ext.nlp.TextNetworkUtil;
import de.visone.gui.tabs.option.BooleanOptionItem;
import de.visone.gui.tabs.option.IntegerOptionItem;

/**
 * Crawls a site (or the entire internet), stopping at a given depth or after
 * reaching the page limit, and produces a graph representing the link
 * structure.
 * 
 * @author Joschi
 * @author matthias
 */
public class CrawlLinksCard extends AbstractCrawlCard {
	private static final String CARD_NAME = "crawl link structure";
	private IntegerOptionItem maxDepth;
	private IntegerOptionItem limit;
	private BooleanOptionItem onlySameHost;
	private BooleanOptionItem textAsWell;
	private BooleanOptionItem readNoFollow;
	private IntegerOptionItem meanDelay;
	private IntegerOptionItem coolDown;
	private BooleanOptionItem ignoreErrors;

	/**
	 * Create the crawler card.
	 * 
	 * @param mediator
	 *            the {@link Mediator}
	 */
	public CrawlLinksCard(final Mediator mediator) {
		super(CARD_NAME, mediator);
	}

	@Override
	protected boolean wantsIntro() {
		return true;
	}

	@Override
	protected void fillAdditionalImportantOptions() {
		maxDepth = new IntegerOptionItem(2, 0, 20);
		limit = new IntegerOptionItem(1000, 1, 10000, 1000);
		onlySameHost = new BooleanOptionItem();
		textAsWell = new BooleanOptionItem();

		addOptionItem(maxDepth, "max depth");
		addOptionItem(limit, "page limit");
		onlySameHost.setValue(true);
		addOptionItem(onlySameHost, "same host only");
		addOptionItem(textAsWell, "store text");
	}

	@Override
	protected void fillAdditionalObscureOptions() {
		ignoreErrors = new BooleanOptionItem();
		ignoreErrors.setValue(true);
		addOptionItem(ignoreErrors, "ignore errors");
		meanDelay = new IntegerOptionItem(1000, 0, 10000, 1000);
		coolDown = new IntegerOptionItem(5000, 0, 20000, 1000);
		addOptionItem(meanDelay, "mean delay");
		addOptionItem(coolDown, "cool down after error");
		readNoFollow = new BooleanOptionItem();
		readNoFollow.setValue(true);
		addOptionItem(readNoFollow, "respect nofollow");
	}

	@Override
	protected Settings createSettings(final String url) {
		final Settings s = super.createSettings(url);
		s.meanDelay = meanDelay.getValue();
		s.coolDown = coolDown.getValue();
		s.doText = textAsWell.getValue();
		s.onlySameHost = onlySameHost.getValue();
		s.readNoFollow = readNoFollow.getValue();
		s.maxDepth = maxDepth.getValue();
		s.killLimit = limit.getValue();
		return s;
	}

	/** {@inheritDoc} */
	@Override
	public CrawlListener getCrawlListener(final Settings s) {
		final Graph graph = new Graph();
		final CrawlAlgorithm algo = new CrawlAlgorithm(s.doText, graph);

		return new CrawlListener() {
			@Override
			public void pageCrawled(final Content c) {
				algo.processContents(c);
			}

			@Override
			public void close() throws IOException {
				final TransportGraph tg = TransportGraphConverter
						.createTransportGraph(graph);
				TextNetworkUtil.createNetwork(tg, mediator);
			}
		};
	}

	@Override
	protected boolean getHaltOnError() {
		return !ignoreErrors.getValue();
	}
}
