/*
 *  Copyright 2015 Brno University of Technology 
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License. 
 */
package cz.vutbr.feec.graph;

import java.util.LinkedList;
import java.util.PriorityQueue;

import org.apache.log4j.Logger;

import cz.vutbr.feec.project.GlobalParameters;

public class Dijkstra {

	private static Logger log = Logger.getLogger(Dijkstra.class);

	private Graph graph;

	public Dijkstra(Graph g) {
		this.graph = g;
	}

	public LinkedList<Path> getPaths(Router from, Router to, double factor) {
		LinkedList<Path> result = new LinkedList<Path>();

		PriorityQueue<Path> prioFronta = new PriorityQueue<Path>();
		Path c = new Path(graph);
		c.addNode(from);
		prioFronta.add(c);
		Double closest = null;
		while (!prioFronta.isEmpty()) {
			log.debug("Toto jsou mozne cesty " + prioFronta);
			Path tmp = prioFronta.remove();
			log.debug("Nejkratsi cesta z cele fronty je " + tmp);
			if (tmp.isAtDestination(to)) {
				log.debug("isAtDestination" + tmp.isAtDestination(to));
				if (closest == null) {
					closest = (double) tmp.getCost();
					log.debug("cost = " + tmp.getCost());
				}
				log.debug("add to result");
				if (tmp.getCost() > factor * closest) {
					// konec jen po prekroceni jiste delky
					return result;
				}
				result.add(tmp);
				//return result;
				} else {
				log.debug("Cesta " + tmp + " zatim nevede do cilovehu uzlu "
						+ to);
				for (Router u : tmp.getLast().getNeighbors()) {
					log.debug("Ceste " + tmp + " pridavam " + u);
					Path kopie = tmp.cloneAndAddNode(u);
					if (kopie.getCost() < GlobalParameters.INFINITY) { // pokud
																		// je v
																		// ceste
																		// cyklus,
																		// neuvazuj
																		// takovou
																		// cestu
						log.debug("Pridavam cestu " + kopie);
						prioFronta.add(kopie);
					}
				}
			}
		}
		return result;
	}

}
