/*
 *  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.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.LinkedList;

import javafx.application.Platform;
import javafx.concurrent.Task;
import javafx.scene.control.ProgressBar;
import javafx.stage.Stage;

import org.apache.log4j.Logger;

import cz.vutbr.feec.gui.ControllerInitializeGui;
import cz.vutbr.feec.gui.ProgressBarRT;
import cz.vutbr.feec.gui.ProgressBarRoutingTable;
import cz.vutbr.feec.libraryClasses.GuiMethods;
import cz.vutbr.feec.project.GlobalParameters;

public class RoutingTable implements Serializable {
	private static Logger log = Logger.getLogger(RoutingTable.class);
	private HashMap<String, HashMap<String, LinkedList<Path>>> paths = new HashMap<String, HashMap<String, LinkedList<Path>>>();

	int i = 0;

	public RoutingTable(final Graph g) {
		
		
		final int size = g.getRouters().size();
		System.out.println("pocet routrov je  " + size);
		
		// nastav visible progressBar + disable vsetko ostatne
		GuiMethods.progressBarSetVisible(true);
		final Task progressTask = new Task<Void>() {
			@Override
			protected Void call() throws Exception {
				// TODO Auto-generated method stub
				int current = 0;
				boolean set = true;
				while (i != size) {
					Thread.sleep(1000);
					System.out.println("cyklus " + i);
					// ked dlho trva medzi dvoma routrami, nejaky preblik
					if(current == i){
						if(set){
							updateProgress(i, size);
							set = false;
						}
						else{
							updateProgress(i+0.5, size);
							set = true;
						}
					}
					else{
					current = i;
					updateProgress(i, size);
					}
				}
				// zrusit progress bar a spristupnit tlacitka
				GuiMethods.progressBarSetVisible(false);
				return null;
			}
		};

		final Task rtTask = new Task<Void>() {
			@Override
			protected Void call() throws Exception {
				// TODO Auto-generated method stub
				long startTime = System.currentTimeMillis();
				Dijkstra d = new Dijkstra(g);
				for (Router fromRouter : g.getRouters()) {
					// pri kazdom hotovom routri chcem updatnut
					// progressBar
					i = i + 1;
					System.out.println("dalsi router");
					if(GlobalParameters.progressCanceled){
						return null;
					}
					

					log.debug("name " + fromRouter);
					HashMap<String, LinkedList<Path>> map = new HashMap<String, LinkedList<Path>>();
					for (Router toRouter : g.getRouters()) {
						if (fromRouter == toRouter) {
							// cesta k sobe samemu
							continue;
						}
						log.debug("Dijkstra from " + fromRouter + " -> "
								+ toRouter);
						LinkedList<Path> pList = d.getPaths(fromRouter,
								toRouter, GlobalParameters.factor);
						log.debug("pList getPaths");
						map.put(toRouter.getData(), pList);
						log.debug("vlozene do mapy");
					}
					log.debug("paths.put");
					paths.put(fromRouter.getData(), map);
					log.debug("vlozene");
				}
				long endTime = System.currentTimeMillis();
				System.out.println("Routing table computing time= "+(endTime - startTime)+" ms");
				return null;
			}
		};
		
		Task progressControl = new Task<Void>() {
			@Override
			protected Void call() throws Exception {
				// TODO Auto-generated method stub
				while (i != size) {
				Thread.sleep(500);
				//ceknut ci nebolo stlacene cancel uzivatelom a zabit vlakna
				if(GlobalParameters.progressCanceled){
					System.out.println("zabijam vlakna");
					progressTask.cancel();
					//rtTask.cancel();
					GuiMethods.progressBarSetVisible(false);
					rtTask.cancel(true);
					//aby sa necyklilo
					return null;
					}
				}
				return null;
			}
		};
		
		
		GlobalParameters.progressRT.progressProperty().bind(
				progressTask.progressProperty());
		new Thread(progressControl).start();
		new Thread(progressTask).start();
		new Thread(rtTask).start();
		
		
		
	}

	public LinkedList<Path> getPaths(Router fromNode, Router toNode) {
		return paths.get(fromNode.getData()).get(toNode.getData());
	}

	public void saveToFile(String filename) {
		// save the object to file
		FileOutputStream fos = null;
		ObjectOutputStream out = null;
		try {
			fos = new FileOutputStream(filename);
			out = new ObjectOutputStream(fos);
			out.writeObject(this);

			out.close();
		} catch (Exception ex) {
			ex.printStackTrace();
		}
	}

	public static RoutingTable loadFromFile(String filename) {
		// read the object from file
		// save the object to file
		FileInputStream fis = null;
		ObjectInputStream in = null;
		try {
			fis = new FileInputStream(filename);
			in = new ObjectInputStream(fis);
			RoutingTable rt = (RoutingTable) in.readObject();
			in.close();

			return rt;
		} catch (Exception ex) {
			ex.printStackTrace();
		}
		return null;
	}

}
