package cz.vutbr.feec.libraryClasses;

import ij.process.ByteProcessor;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Vector;

import org.controlsfx.control.action.Action;
import org.controlsfx.dialog.Dialog;
import org.controlsfx.dialog.Dialogs;

import cz.vutbr.feec.graph.Dijkstra;
import cz.vutbr.feec.graph.Path;
import cz.vutbr.feec.graph.Router;
import cz.vutbr.feec.graph.RoutingTable;
import cz.vutbr.feec.gui.AccidentCanvas;
import cz.vutbr.feec.gui.ControllerInitializeGui;
import cz.vutbr.feec.gui.NewProjectWindow;
import cz.vutbr.feec.gui.OtherObjectInCanvas;
import cz.vutbr.feec.gui.ProgressBarRT;
import cz.vutbr.feec.gui.SettingsWindow;
import cz.vutbr.feec.newGui.MainGuiController;
import cz.vutbr.feec.newGui.MainNewProjectGui;
import cz.vutbr.feec.newGui.MainSettingsGui;
import cz.vutbr.feec.project.GlobalParameters;
import cz.vutbr.feec.stockElements.AbstractStockCell;
import cz.vutbr.feec.stockElements.Accident;
import cz.vutbr.feec.stockElements.AccidentCell;
import cz.vutbr.feec.stockElements.BorderCell;
import cz.vutbr.feec.stockElements.CoridorCell;
import cz.vutbr.feec.stockElements.RackCell;
import cz.vutbr.feec.stockElements.RouterCell;
import cz.vutbr.feec.stockElements.Stock;
import cz.vutbr.feec.transportObjects.OtherObjectCrate;
import javafx.fxml.FXML;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
//import javafx.scene.control.Dialogs;
import javafx.scene.control.MenuItem;
import javafx.scene.control.ToggleButton;
//import javafx.scene.control.Dialogs.DialogResponse;
import javafx.scene.effect.BlendMode;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseButton;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.stage.FileChooser;
import javafx.stage.Stage;

public class GuiMethods {

	private static Stock s = Stock.getInstance();
	private static GraphicsContext gc;
	

	// vytvorenie pola
	public static void createField() {
		// pridavam okrajove riadky a stlpce uz pri inicializaci
		int x = (int) ((s.getLength() / s.getDelimiter()));
		int y = (int) ((s.getWidth() / s.getDelimiter()));
		GlobalParameters.lengthField = x;
		GlobalParameters.widthField = y;
		AbstractStockCell[][] pole = new AbstractStockCell[x][y];
		s.setField(pole);
		System.out.println("creating new field " + pole.length);
		// naplnit kazdy stvorcek chodbou na zaciatku
		// + naplnit okraje
		/*
		 * for (int i = 0; i < (s.getLength() / s.getDelimiter()); i++) { for
		 * (int j = 0; j < (s.getWidth() / s.getDelimiter()); j++) { pole[i][j]
		 * = new CoridorCell(i, j); } }
		 */
		// vsetko najskor nastavim na coridor
		for (int i = 0; i < x; i++) {
			for (int j = 0; j < y; j++) {
				pole[i][j] = new CoridorCell(i, j);
			}
		}
		// okraje potom prepisem na hranice pola
		for (int i = 0; i < x; i++) {
			pole[i][0] = new BorderCell(i, 0);
			pole[i][y - 1] = new BorderCell(i, y - 1);
		}
		for (int i = 0; i < y; i++) {
			pole[0][i] = new BorderCell(0, i);
			pole[x - 1][i] = new BorderCell(x - 1, i);
		}
		System.out.println("border OK");

	}

	public static void setCanvas(Canvas canvas) {
		gc = canvas.getGraphicsContext2D();
		GlobalParameters.gc = gc;
		canvas.setWidth(s.getLength());
		canvas.setHeight(s.getWidth());
		GlobalParameters.mainCanvas = canvas;
	}

	public static void createCanvas() {
		// vytvorenie poli
		GuiMethods.createField();
		// vymazat cesty a routre
		clearRoutersAndDistances();
		setCanvas(GlobalParameters.mainCreatingCanvas);
		GlobalParameters.mainScrollPane.setContent(GlobalParameters.mainCreatingCanvas);
		// inicialna velkost canvasu
		// zistit podla ktoreho sa to bude urcovat ci podla sirky alebo vysky
		/*
		 * if ((scrollPane.getWidth() / canvas.getWidth()) < (scrollPane
		 * .getHeight() / canvas.getHeight())) { if ((scrollPane.getWidth() /
		 * canvas.getWidth()) < 1) { zoomRatio = (float) (scrollPane.getWidth()
		 * / canvas.getWidth()); } else { zoomRatio = (float)
		 * (scrollPane.getWidth() / canvas.getWidth()); } } else { if
		 * ((scrollPane.getHeight() / canvas.getHeight()) < 1) { zoomRatio =
		 * (float) (scrollPane.getHeight() / canvas .getHeight()); } else {
		 * zoomRatio = (float) (scrollPane.getHeight() / canvas .getHeight()); }
		 * }
		 */
		// System.out.println(zoomRatio);

		// vsetky ikony nastavim na enable
		iconsInitialSetEnable(ControllerInitializeGui.getInitialIcons());
		// menu tak isto enable
		ControllerInitializeGui.enableMenu();
		// vymazem frontu redo undo
		GlobalParameters.edit.removeAll();
		cellInformation(ControllerInitializeGui.cellCurrentX,
				ControllerInitializeGui.cellCurrentY);

		// GuiMethods.createZoomedCanvas(Stock.getBackgroundColor(), gc,
		// canvas);

	}

	public static int getClickedFieldX(double d) {
		while ((d % (s.getDelimiter() * ControllerInitializeGui.getZoomRatio())) != 0) {
			d = d - 1;
		}
		return (int) d;
	}

	public static int getClickedFieldY(double d) {
		while ((d % (s.getDelimiter() * ControllerInitializeGui.getZoomRatio())) != 0) {
			d = d - 1;
		}
		return (int) d;
	}

	public static int getClickedIndexOfFieldX(int x) {
		x = (int) (x / s.getDelimiter() / ControllerInitializeGui
				.getZoomRatio());
		return x;
	}

	public static int getClickedIndexOfFieldY(int y) {
		y = (int) (y / s.getDelimiter() / ControllerInitializeGui
				.getZoomRatio());
		return y;
	}

	public static int getFieldFromIndexX(int x) {
		x = (int) (x * s.getDelimiter() * ControllerInitializeGui
				.getZoomRatio());
		return x;
	}

	public static int getFieldFromIndexY(int y) {
		y = (int) (y * s.getDelimiter() * ControllerInitializeGui
				.getZoomRatio());
		return y;
	}

	public static void cellInformation(int x, int y) {
/*
		s.getFieldIndex(ControllerInitializeGui.getCellCurrentX(),
				ControllerInitializeGui.getCellCurrentY()).setCurrent(false);
*/
		ControllerInitializeGui.setCellCurrentX(x);
		ControllerInitializeGui.setCellCurrentY(y);

		//s.getFieldIndex(x, y).setCurrent(true);
		s.setIsCurrent(s.getFieldIndex(x, y));

		// nastavim novu ako zvyraznenu
		GuiPainting.createZoomedCanvas();
		// zakomentovane kvoli druhemu GUI
		/*
		 * ControllerInitializeGui.cellSelectionX.setText(String.valueOf(x));
		 * ControllerInitializeGui.cellSelectionY.setText(String.valueOf(y));
		 * 
		 * if (s.getFieldIndex(x, y).getClass() == BorderCell.class) return;
		 * else if (s.getFieldIndex(x, y).getClass() == ReckCell.class) {
		 * ControllerInitializeGui.cellSelectionLabel.setText("Reck"); } else if
		 * (s.getFieldIndex(x, y).getClass() == AccidentCell.class) {
		 * ControllerInitializeGui.cellSelectionLabel.setText("Accident");
		 * 
		 * } else {
		 * ControllerInitializeGui.cellSelectionLabel.setText("Coridor");
		 * 
		 * } try { System.out.println("---- Cell information for: " + x + "," +
		 * y); System.out.println(s.getFieldIndex(x, y)); for (int i = 0; i <
		 * s.getFieldIndex(x, y).getClosestRouters() .size(); i++) {
		 * System.out.println("Router " + s.getFieldIndex(x,
		 * y).getClosestRouters().get(i) + " vzdialenost " + s.getFieldIndex(x,
		 * y).getClosestDistances().get(i)); }
		 * 
		 * } catch (Exception e) {
		 * System.out.println("exceptin - nenastavene parametre"); }
		 */
	}

	public static boolean validationCellSelection() {

		String warning = "";

		boolean isOK = true;
		/*
		 * if (s.getField() == null) return false; try { int x =
		 * Integer.valueOf(ControllerInitializeGui.cellSelectionX .getText());
		 * if ((x < 0) || (x >= s.getLength() / s.getDelimiter())) {
		 * 
		 * ControllerInitializeGui.cellSelectionX.setText(String
		 * .valueOf(ControllerInitializeGui.getCellCurrentX())); warning =
		 * "x not found! "; ControllerInitializeGui.cellSelectionWarningLabel
		 * .setText(warning); isOK = false; }
		 * 
		 * } catch (Exception e) {
		 * ControllerInitializeGui.cellSelectionX.setText(String
		 * .valueOf(ControllerInitializeGui.getCellCurrentX())); warning =
		 * "x not found! ";
		 * ControllerInitializeGui.cellSelectionWarningLabel.setText(warning);
		 * isOK = false; } try { int y =
		 * Integer.valueOf(ControllerInitializeGui.cellSelectionY .getText());
		 * if ((y < 0) || (y >= s.getWidth() / s.getDelimiter())) {
		 * ControllerInitializeGui.cellSelectionY.setText(String
		 * .valueOf(ControllerInitializeGui.getCellCurrentY())); warning =
		 * warning + "y not found!";
		 * ControllerInitializeGui.cellSelectionWarningLabel .setText(warning);
		 * 
		 * isOK = false; }
		 * 
		 * } catch (Exception e) { warning = warning + "y not found!";
		 * ControllerInitializeGui.cellSelectionY.setText(String
		 * .valueOf(ControllerInitializeGui.getCellCurrentY()));
		 * ControllerInitializeGui.cellSelectionWarningLabel.setText(warning);
		 * isOK = false; } if (isOK == true)
		 * ControllerInitializeGui.cellSelectionWarningLabel.setText("");
		 */
		return isOK;
	}

	public static boolean validationReckSize() {
		String warning = "";

		boolean isOK = true;
		/*
		 * if (s.getField() == null) {
		 * ControllerInitializeGui.reckSizeWarningLabel
		 * .setText("define stock!"); return false; } try { int x = Integer
		 * .valueOf(ControllerInitializeGui.reckSizeX.getText()); if ((x < 0) ||
		 * (x >= s.getLength())) {
		 * 
		 * ControllerInitializeGui.reckSizeX.setText("NA"); warning =
		 * "x impossible!";
		 * ControllerInitializeGui.reckSizeWarningLabel.setText(warning); isOK =
		 * false; } // musi byt delitelne delimitrom aby sa to zmestilo do
		 * stvorcekov else if (x % s.getDelimiter() != 0) {
		 * ControllerInitializeGui.reckSizeX.setText("NA"); warning =
		 * "modulo!!";
		 * ControllerInitializeGui.reckSizeWarningLabel.setText(warning); isOK =
		 * false; }
		 * 
		 * } catch (Exception e) {
		 * ControllerInitializeGui.reckSizeX.setText("NA"); warning =
		 * "x impossible! ";
		 * ControllerInitializeGui.reckSizeWarningLabel.setText(warning); isOK =
		 * false; } try { int y = Integer
		 * .valueOf(ControllerInitializeGui.reckSizeY.getText()); if ((y < 0) ||
		 * (y >= s.getWidth())) {
		 * ControllerInitializeGui.reckSizeY.setText("NA"); warning = warning +
		 * "y impossible!";
		 * ControllerInitializeGui.reckSizeWarningLabel.setText(warning); isOK =
		 * false; } else if (y % s.getDelimiter() != 0) {
		 * ControllerInitializeGui.reckSizeY.setText("NA"); warning =
		 * "modulo!!";
		 * ControllerInitializeGui.reckSizeWarningLabel.setText(warning); isOK =
		 * false; }
		 * 
		 * } catch (Exception e) { warning = warning + "y impossible!";
		 * ControllerInitializeGui.reckSizeY.setText("NA");
		 * ControllerInitializeGui.reckSizeWarningLabel.setText(warning); isOK =
		 * false; } if (isOK == true)
		 * ControllerInitializeGui.reckSizeWarningLabel.setText("");
		 */
		return isOK;
	}

	/*
	 * public static void createReck(int xInField, int yInField) { if
	 * (ControllerInitializeGui.lastUsedCombobox.getSelectionModel().isEmpty())
	 * {
	 * ControllerInitializeGui.reckSizeWarningLabel.setText("define reck size");
	 * return; } String[] numberStrs = ControllerInitializeGui.lastUsedCombobox
	 * .getSelectionModel().getSelectedItem().split(","); int x =
	 * Integer.parseInt(numberStrs[0]); int y = Integer.parseInt(numberStrs[1]);
	 * // cez kolko stvorcekov to prechadza x = x / s.getDelimiter(); y = y /
	 * s.getDelimiter(); if
	 * (ControllerInitializeGui.positionCombobox.getSelectionModel()
	 * .getSelectedItem() == "VERTICAL") { for (int i = xInField; i < xInField +
	 * x; i++) { for (int j = yInField; j < yInField + y; j++) {
	 * s.getFieldIndex(i, j).setReck(true); } }
	 * 
	 * } else { // horizontal for (int i = xInField; i < xInField + y; i++) {
	 * for (int j = yInField; j < yInField + x; j++) { s.getFieldIndex(i,
	 * j).setReck(true);
	 * 
	 * }
	 * 
	 * }
	 * 
	 * } }
	 */
	public static void reckCreating(int xInField, int yInField, boolean isClick) {

		int maximumFieldRight;
		int maximumFieldDown;
		int x = 0;
		int y = 0;
		Image image = null;
		int cellType = 0;
		// 0 = reck
		// 1 = reck rotated
		// 2 = other
		// 3 = delete
		// 4 = accident
		/*
		 * if
		 * (ControllerInitializeGui.lastUsedCombobox.getSelectionModel().isEmpty
		 * ()) {
		 * ControllerInitializeGui.reckSizeWarningLabel.setText("define reck size"
		 * ); return; }
		 * 
		 * String[] numberStrs = ControllerInitializeGui.lastUsedCombobox
		 * .getSelectionModel().getSelectedItem().split(","); int x =
		 * Integer.parseInt(numberStrs[0]); int y =
		 * Integer.parseInt(numberStrs[1]); // cez kolko stvorcekov to prechadza
		 * 
		 * 
		 * x = x / s.getDelimiter(); y = y / s.getDelimiter();
		 */
		if (GlobalParameters.reckCanvas.getSelectedReck() != null) {

			if (!GlobalParameters.reckCanvas.isHorizontal()) {
				x = GlobalParameters.reckCanvas.getSelectedReck().getSizeX();
				y = GlobalParameters.reckCanvas.getSelectedReck().getSizeY();
				image = GlobalParameters.reckImage;
				cellType = 0;

			} else {
				x = GlobalParameters.reckCanvas.getSelectedReck().getSizeY();
				y = GlobalParameters.reckCanvas.getSelectedReck().getSizeX();
				image = GlobalParameters.reckRotatedImage;
				cellType = 1;
			}
		} else if (GlobalParameters.otherCanvas.getSelectedObject() != null) {
			x = GlobalParameters.otherCanvas.getSelectedObject().getSizeX();
			y = GlobalParameters.otherCanvas.getSelectedObject().getSizeY();
			image = GlobalParameters.otherCanvas.getSelectedObject().getImage();
			cellType = 2;
		} else if (GlobalParameters.deleteButton.isSelected()) {
			x = 1;
			y = 1;
			// obrazok zatial len takyto
			image = GlobalParameters.deleteImage;
			cellType = 3;
		} else if (GlobalParameters.accidentCanvas.getSelectedAccident() != null) {
			x = 1;
			y = 1;
			// obrazok zatial len takyto
			image = GlobalParameters.accidentCanvas.getSelectedAccident()
					.getImage();
			cellType = 4;
		}
		// pridane aby sa nemohli vytvarat regale na okrajoch, ani tam vstupit s
		// regalom
		maximumFieldRight = (int) (s.getLength() / s.getDelimiter() - x - 1);
		maximumFieldDown = (int) (s.getWidth() / s.getDelimiter() - y - 1);

		try {
			int whereStartX = 0;
			int whereStartY = 0;

			// if (ControllerInitializeGui.positionCombobox.getSelectionModel()
			// .getSelectedItem() == "VERTICAL") {

			// if (!GlobalParameters.reckCanvas.isHorizontal()) {

			if (xInField <= maximumFieldRight) {
				whereStartX = xInField;
			} else {
				whereStartX = maximumFieldRight;
			}
			if (yInField <= maximumFieldDown) {
				whereStartY = yInField;
			} else {
				whereStartY = maximumFieldDown;
			}
			if (xInField == 0) {
				whereStartX = 1;
			}
			if (yInField == 0) {
				whereStartY = 1;
			}
			// sme mimo hranic, zobrazit najblizsiu moznost
			for (int i = whereStartX; i < whereStartX + x; i++) {
				for (int j = whereStartY; j < whereStartY + y; j++) {
					// pokial sa aj kliklo tak nastavit na regale
					if (isClick) {/*
								 * ReckCell reck = new ReckCell(i, j);
								 * s.setFieldIndex(reck, i, j);
								 */
						// menim primo do prvych podmienok vytvorim bunku ktora
						// sa bude kreslit
						// a tu ju len dam do pola
						switch (cellType) {
						case 0:
							RackCell reck = new RackCell(i, j);
							s.setFieldIndex(reck, i, j);
							break;
						case 1:
							RackCell reckRotated = new RackCell(i, j);
							reckRotated.setRotated(true);
							s.setFieldIndex(reckRotated, i, j);
							System.out.println("ReckRotated");
							break;
						case 2:
							System.out.println("OTHEEEER");
							// pokial to je priechozie
							if (GlobalParameters.otherCanvas
									.getSelectedObject().isAccessible()) {
								// vytvorim novy coridorCell (kvoli redo undo),
								// akurat zmenim obrazok

								CoridorCell cc = new CoridorCell(i, j);
								cc.setImage(image);
								s.setFieldIndex(cc, i, j);
								s.getRamps().add(s.getFieldIndex(i, j));
								System.out.println("size Ramps= "
										+ s.getRamps().size());
							} else {
								BorderCell bc = new BorderCell(i, j);
								bc.setImage(image);
								s.setFieldIndex(bc, i, j);
								System.out
										.println("creating other inAccessible object");

							}
							break;
						case 3:
							// ceknut na ktorom sme tabe
							// ak na prvom tak sa vsetko moze kludne prepisovat
							//
							// ak na druhom kde sa priadvaju accidenty, tak iba
							// accidenty odstranovat
							System.out.println("delete");
							if (GlobalParameters.tabPane
									.getSelectionModel().getSelectedItem() == GlobalParameters.maintenanceTab) {
								// mozem mazat len accidenty
								//if (s.getFieldIndex(i, j).getClass() == AccidentCell.class) {
								//ak sa kliklo na accident
								System.out.println("druhy tab");
								if (s.containsAccident(s.getFieldIndex(i, j))) {
									System.out.println("click na accident");
									// validacna hlaska
									/*
									DialogResponse response = Dialogs
											.showConfirmDialog(
													GlobalParameters.primaryStage,
													"Do you want to continue?",
													"This action will remove this accident",
													"");
									if (response == DialogResponse.YES) {
									*/
									Action response = Dialogs.create()
									        .owner(GlobalParameters.primaryStage)
									        .title("")
									        .masthead("This action will remove this accident")
									        .message("Do you want to continue?")
									        .showConfirm();
									if (response == Dialog.ACTION_YES) {
										
										
										// odstran nehodu
										/*
										s.removeAccident((AccidentCell) s
												.getFieldIndex(i, j));
									*/
										s.removeCellFromAccident(s.getFieldIndex(i,j));
									}
									return;
								}

							}
							else{
							// pokial sa klika na koridor bunku, kde nie je co
							// mazat, tak return
							// akurat by to rozhadzalo undo a redo
							if (s.getFieldIndex(i, j).getClass() == CoridorCell.class) {
								System.out.println("coridor");
								CoridorCell cc = (CoridorCell) s.getFieldIndex(
										i, j);
								System.out.println(cc.getImage());
								// if (!cc.isImage()) {
								if (!s.containsRamp(cc)) {
									System.out.println(cc.getImage());
									// musim vymazat posledny stav z undo,
									// pretoze sa to ulozilo este pred
									// touto metodou
									System.out.println("bez obrazku");
									GlobalParameters.edit.getUndo()
											.removeLast();
									return;
								}

								s.removeRamp(s.getFieldIndex(i, j));
								CoridorCell c = new CoridorCell(i, j);
								s.setFieldIndex(c, i, j);
								break;
							}
							CoridorCell c = new CoridorCell(i, j);
							s.setFieldIndex(c, i, j);
							}
							break;
						case 4:
							
							System.out.println("vytvaram");
							AbstractStockCell cc = s
									.getFieldIndex(i, j);
							/*
							AccidentCell a = new AccidentCell(i, j, cc);
							s.addAccident(a);
							System.out.println("accident added");
							*/
							//pridam do accidentcells
							if(!s.containsAccident(cc)){
								if(cc.getClass() != RackCell.class){
							s.getAccidentCells().add(cc);
								}
							}
							break;
						}

					}
					/*
					 * GuiPainting.drawInFieldCell(
					 * ControllerInitializeGui.getCanvas(),
					 * ControllerInitializeGui.getGc(), Color.YELLOW,
					 * getFieldFromIndexX(i), getFieldFromIndexY(j));
					 */
					GuiPainting.drawImage(image,
							GuiMethods.getFieldFromIndexX(i),
							GuiMethods.getFieldFromIndexY(j));
				}
			}
			// }
			/*
			 * maximumFieldRight = (int) (s.getLength() / s.getDelimiter() - x);
			 * maximumFieldDown = (int) (s.getWidth() / s.getDelimiter() - y );
			 */
			/*
			 * } else { maximumFieldRight = (int) (s.getLength() /
			 * s.getDelimiter() - y - 1); maximumFieldDown = (int) (s.getWidth()
			 * / s.getDelimiter() - x - 1);
			 * 
			 * // horizontal if (xInField <= maximumFieldRight) { whereStartX =
			 * xInField;
			 * 
			 * } else { whereStartX = maximumFieldRight; } if (yInField <=
			 * maximumFieldDown) { whereStartY = yInField; } else { whereStartY
			 * = maximumFieldDown; }
			 * 
			 * for (int i = whereStartX; i < whereStartX + y; i++) { for (int j
			 * = whereStartY; j < whereStartY + x; j++) { if (isClick) {
			 * ReckCell reck = new ReckCell(i, j); s.setFieldIndex(reck, i, j);
			 * } /* GuiPainting.drawInFieldCell(
			 * ControllerInitializeGui.getCanvas(),
			 * ControllerInitializeGui.getGc(), Color.YELLOW,
			 * getFieldFromIndexX(i), getFieldFromIndexY(j));
			 * 
			 * // musim ho o 90 stupnov otocit GuiPainting.drawImage(
			 * GlobalParameters.reckRotatedImage,
			 * GuiMethods.getFieldFromIndexX(i),
			 * GuiMethods.getFieldFromIndexY(j)); }
			 * 
			 * }
			 * 
			 * }
			 */
		} catch (Exception e) {
			System.out.println("tuto treba s tym nieco robit");
			// TODO: handle exception
		}

	}

	public static void fieldChanged() {
		GlobalParameters.edit.addStep();
		// musim vymazat este redo frontu
		GlobalParameters.edit.getRedo().removeAll(
				GlobalParameters.edit.getRedo());
		// nastavim v parametrocho ze to nie je ulozene
		GlobalParameters.isSaved = false;
		setNameOfProject();

	}

	public static void writeProject(File file) {
		FileOutputStream fos = null;
		try {
			fos = new FileOutputStream(file);

			BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos));
			saveInitData(bw);
			saveRecks(bw);
			savePaths(bw);
			saveAccidents(bw);
			if (s.getRoutingTable() != null) {
				String path = GlobalParameters.fileProject.getParentFile()
						.getPath();
				s.getRoutingTable().saveToFile(path +"/"+GlobalParameters.getNameProject()+"RT.rt");
			}
			bw.close();
		} catch (Exception e) {
			// TODO: handle exception
		}

	}

	private static void saveRecks(BufferedWriter bw) {
		Vector<AbstractStockCell> rotatedRecks = new Vector<AbstractStockCell>();
		Vector<AbstractStockCell> ramps = new Vector<AbstractStockCell>();
		Vector<AbstractStockCell> objects = new Vector<AbstractStockCell>();
		try {
			bw.write("reckCells=;");

			// prejdem cele pole a ktora bunka je reck, tak zapisem
			int x = (int) ((s.getLength() / s.getDelimiter()));
			int y = (int) ((s.getWidth() / s.getDelimiter()));
			AbstractStockCell[][] pole = s.getField();
			for (int i = 0; i < x; i++) {
				for (int j = 0; j < y; j++) {
					if (pole[i][j].getClass() == RackCell.class) {
						RackCell rc = (RackCell) pole[i][j];
						if (!rc.isRotated()) {
							bw.write(rc.getX() + "," + rc.getY() + ";");
						} else {
							rotatedRecks.add(rc);
						}
					} else if (pole[i][j].getClass() == CoridorCell.class) {
						CoridorCell cc = (CoridorCell) pole[i][j];
						// znamena ze ma obrazok rampy
						/*
						 * if (cc.isImage()) { ramps.add(cc); }
						 */
					} else if (pole[i][j].getClass() == BorderCell.class) {
						BorderCell bc = (BorderCell) pole[i][j];
						// znamena ze je to nepriechodne, nejaky obrazok
						if (bc.isImage()) {
							objects.add(bc);
						}
					}
				}
				// TODO Auto-generated method stub
			}

			// potrebujem pridat rampy co su prepisane routrami
			Vector<AbstractStockCell> v = s.getRamps();
			for (int i = 0; i < v.size(); i++) {
				ramps.add((AbstractStockCell) v.get(i));
			}
			bw.newLine();
			// tu skoncilo vypisovanie normalnych reckov
			// vypisem na dalsiu line rotated recky
			writeCollectionToFile(bw, rotatedRecks, "rotatedRecks=;");
			// dalsia line rampy
			writeCollectionToFile(bw, ramps, "ramps=;");
			// dalsie objekty
			writeCollectionToFile(bw, objects, "border=;");
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	private static void writeCollectionToFile(BufferedWriter bw,
			Vector<AbstractStockCell> vector, String lineName) {

		try {
			bw.write(lineName);

			for (int i = 0; i < vector.size(); i++) {
				AbstractStockCell cell = vector.get(i);
				bw.write(cell.getX() + "," + cell.getY() + ";");

			}
			bw.newLine();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	private static void saveInitData(BufferedWriter bw) {
		try {
			bw.write("length;" + s.getLength() + ";");
			bw.write("width;" + s.getWidth() + ";");
			bw.write("delimiter;" + s.getDelimiter() + ";");
			bw.write("factor;" + GlobalParameters.factor+ ";");
			bw.write("metric;" + GlobalParameters.meterPerSecond+ ";");
			bw.newLine();

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private static void savePaths(BufferedWriter bw) {
		// kazdu cestu vypisem routre, cenu a bunky
		try {
			Vector<Path> paths = s.getPaths();
			Path path;
			Vector<AbstractStockCell> tmp;
			for (int i = 0; i < paths.size(); i++) {
				path = paths.get(i);
				tmp = path.getPath();
				bw.write("Path=;");
				bw.write(path.getCost() + ";");
				bw.write(path.getFirstRouter() + ";");
				bw.write(path.getSecondRouter() + ";");
				for (int j = 0; j < tmp.size(); j++) {
					bw.write(tmp.get(j).getX() + "," + tmp.get(j).getY() + ";");
				}
				bw.newLine();
			}

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	private static void saveAccidents(BufferedWriter bw) {
		try {
			bw.write("End Paths");
			bw.newLine();
			bw.write("Accidents=;");
			AbstractStockCell a;
			/*
			Vector<Accident> accidents = s.getAccidents();
			for (int i = 0; i < accidents.size(); i++) {
				a = accidents.get(i).getCell();
				bw.write(a.getX() + "," + a.getY() + ";");
				bw.newLine();
			}
*/
			Vector<AbstractStockCell> accidents = s.getAccidentCells();
			for (int i = 0; i < accidents.size(); i++) {
				a = accidents.get(i);
				bw.write(a.getX() + "," + a.getY() + ";");
			}
			bw.newLine();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	private static void loadPaths(BufferedReader br) {
		try {
			for (String line = br.readLine(); line.startsWith("Path"); line = br
					.readLine()) {

				Path path = new Path(s.getGraph());
				s.getPaths().add(path);
				System.out.println("creating path " + path.getCost());

				String[] nodes = line.split(";");
				int cost = Integer.valueOf(nodes[1]);
				path.setCost(cost);
				// pozeram router
				for (int i = 2; i < 4; i++) {
					if (!nodes[i].equals("null")) {
						String[] xy = nodes[i].split(",");
						int x = Integer.valueOf(xy[1]);
						int y = Integer.valueOf(xy[2]);
						// vytvorim router
						Router router = new Router(x, y);
						s.addRouter(router);
						// pridavam routerCell do pola
						RouterCell rc = new RouterCell(x, y);
						// nastavim vazbu na router
						rc.setRouter(router);
						System.out.println("creating router cell");
						s.setFieldIndex(rc, x, y);
						if (path.getFirstRouter() == null) {
							path.setFirstRouter(router);
						} else {
							path.setSecondRouter(router);
						}

					}
				}
				for (int i = 4; i < nodes.length; i++) {
					// zacinam od 4 pretze to je prva bunka chodby co je v ceste
					String[] xy = nodes[i].split(",");
					int x = Integer.valueOf(xy[0]);
					int y = Integer.valueOf(xy[1]);
					path.addCellToPath(s.getFieldIndex(x, y));
				}
				System.out.println("cesta ok " + path.getCost());

			}
			System.out.println("loadnute cesty ok");

		} catch (Exception e) {
			// TODO: handle exception
		}
	}

	private static void loadAccidents(BufferedReader br) throws IOException {
		System.out.println("OK pred readline");
		String data = br.readLine();
		System.out.println(br.readLine());
		String[] nodes = data.split(";");
		System.out.println("pred cyklom");
		/*
		for (int i = 1; i < nodes.length; i++) {
			System.out.println("cyklus");
			String[] xy = nodes[i].split(",");
			int x = Integer.valueOf(xy[0]);
			int y = Integer.valueOf(xy[1]);
			CoridorCell c = (CoridorCell) s.getFieldIndex(x, y);
			AccidentCell a = new AccidentCell(x, y, c);
			s.addAccident(a);
		}
		*/
		for (int i = 1; i < nodes.length; i++) {
			System.out.println("cyklus");
			String[] xy = nodes[i].split(",");
			int x = Integer.valueOf(xy[0]);
			int y = Integer.valueOf(xy[1]);
			s.getAccidentCells().add(s.getFieldIndex(x, y));
			
		}

	}

	public static void openProject(File file) {
		try {
			FileReader fr = new FileReader(file);
			BufferedReader br = new BufferedReader(fr);
			loadInitData(br);
			System.out.println("loadInitOK");
			loadRecks(br);
			System.out.println("load recks ok");
			GuiMethods.clearRoutersAndDistances();
			System.out.println("clearing Routers");
			loadPaths(br);
			GraphCreatingMethods.createGraph();
			System.out.println("graf vytvoreny");
			loadAccidents(br);
			br.close();
			GuiPainting.createZoomedCanvas();
		} catch (Exception e) {
			System.out.println("exceptionINPUTSTERAM");
			// TODO: handle exception
		}
	}

	private static void loadRecks(BufferedReader br) {
		try {
			String data = br.readLine();
			String[] nodes = data.split(";");
			for (int i = 1; i < nodes.length; i++) {
				String[] xy = nodes[i].split(",");
				int x = Integer.valueOf(xy[0]);
				int y = Integer.valueOf(xy[1]);
				s.setFieldIndex(new RackCell(x, y), x, y);
			}
			// normalne recky skoncili tu
			// rotated recky
			data = br.readLine();
			nodes = data.split(";");
			for (int i = 1; i < nodes.length; i++) {
				String[] xy = nodes[i].split(",");
				int x = Integer.valueOf(xy[0]);
				int y = Integer.valueOf(xy[1]);
				RackCell rc = new RackCell(x, y);
				rc.setRotated(true);
				s.setFieldIndex(rc, x, y);
			}
			// rampy
			data = br.readLine();
			nodes = data.split(";");
			for (int i = 1; i < nodes.length; i++) {
				String[] xy = nodes[i].split(",");
				int x = Integer.valueOf(xy[0]);
				int y = Integer.valueOf(xy[1]);
				CoridorCell cc = new CoridorCell(x, y);
				cc.setImage(GlobalParameters.rampImage);
				s.setFieldIndex(cc, x, y);
				s.getRamps().add(cc);
			}
			data = br.readLine();
			nodes = data.split(";");
			for (int i = 1; i < nodes.length; i++) {
				String[] xy = nodes[i].split(",");
				int x = Integer.valueOf(xy[0]);
				int y = Integer.valueOf(xy[1]);
				BorderCell bc = new BorderCell(x, y);
				bc.setImage(GlobalParameters.borderImage);
				s.setFieldIndex(bc, x, y);
			}

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

	private static void loadInitData(BufferedReader br) {
		try {
			String data = br.readLine();
			System.out.println(data);
			String[] nodes = data.split(";");
			String result = nodes[1].substring(0, nodes[1].indexOf("."));
			int length = Integer.valueOf(result);

			System.out.println("l= " + length);
			result = nodes[3].substring(0, nodes[3].indexOf("."));
			int width = Integer.valueOf(result);

			short delimiter = Short.valueOf(nodes[5]);
			double factor = Double.valueOf(nodes[7]);
			int metric = Integer.valueOf(nodes[9]);
			s.setDelimiter(delimiter);
			s.setLength(length);
			s.setWidth(width);
			GlobalParameters.factor = factor;
			GlobalParameters.meterPerSecond = metric;
			System.out.println("mam data");
			GuiMethods.createCanvas();

		} catch (IOException e) {
			// TODO Auto-generated catch block
			System.out.println("exceptionLoadData");
			e.printStackTrace();
		}

	}

	public static void setNameOfProject() {
		try {

			String name = GlobalParameters.getNameProject();
			if (GlobalParameters.isSaved) {
				// nastav normalne meno
				GlobalParameters.primaryStage.setTitle(name);
			} else {
				// bola nejaka zmena nie je to ulozene
				GlobalParameters.primaryStage.setTitle("*" + name);
			}
		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("nie je nazov");
			// nie je ziadny file odkial by sa to cerpalo, takze zmenim meno
			// priamo do stagu
			GlobalParameters.primaryStage.setTitle("*Untitled");
		}

	}

	public static void clearRoutersAndDistances() {
		for (int i = 0; i < s.getRouters().size(); i++) {
			int x = s.getRouters().get(i).getxInField();
			int y = s.getRouters().get(i).getyInField();
			CoridorCell c = new CoridorCell(x, y);
			s.setFieldIndex(c, x, y);
		}
		s.getRouters().removeAllElements();
		s.getPaths().removeAllElements();
		// s.getRamps().removeAll(s.getRamps());
	}

	public static void iconPressed(ImageView icon) {
		if (!icon.isDisable()) {
			icon.setBlendMode(BlendMode.MULTIPLY);
		}
	}

	public static void iconReleased(ImageView icon) {
		icon.setBlendMode(BlendMode.SRC_OVER);

	}

	public static void iconEntered(ImageView icon) {
		if (!icon.isDisable()) {
			icon.setScaleX(1.2);
			icon.setScaleY(1.2);
		}
	}

	public static void iconExited(ImageView icon) {
		icon.setScaleX(1);
		icon.setScaleY(1);
	}

	public static void iconSetDisable(ImageView icon) {
		icon.setOpacity(0.5);
		icon.setDisable(true);
	}

	public static void iconSetEnable(ImageView icon) {
		icon.setOpacity(1);
		icon.setDisable(false);
	}

	public static void iconsInitialSetEnable(Vector<ImageView> icons) {
		for (int i = 0; i < icons.size(); i++) {
			iconSetEnable(icons.get(i));
		}
		GlobalParameters.deleteButton.setDisable(false);
		GlobalParameters.netButton.setDisable(false);
		GlobalParameters.meterButton.setDisable(false);
	}

	// ////////////////////////////////////////////////////////////////////////
	// metody spolocne pre menu a toolbar
	public static void newProject() {
		saveBeforeClose(GlobalParameters.primaryStage);
		NewProjectWindow nw = new NewProjectWindow("", "", "2");
		/*
		  MainNewProjectGui newProject = new MainNewProjectGui();
		  newProject.start(new Stage());
		 */
	}

	public static void options() {
		SettingsWindow sw = new SettingsWindow(
				String.valueOf(GlobalParameters.meterPerSecond),
				String.valueOf(GlobalParameters.factor));
		/*
		 * MainSettingsGui options = new MainSettingsGui(); options.start(new
		 * Stage());
		 */
	}

	public static void undo() {
		try {
			GlobalParameters.edit.getUndoStep();
			// nacitam z unda pole
			GuiPainting.createZoomedCanvas();
			// musim prekreslit co mam

		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("undo exception");

		}
	}

	public static void redo() {
		try {
			GlobalParameters.edit.getRedoStep();
			// nacitam z unda pole
			GuiPainting.createZoomedCanvas();
			// musim prekreslit co mam

		} catch (Exception e) {
			// TODO: handle exception
			System.out.println("redo exception");

		}
	}

	public static void iconsInitialSetDisable(Vector<ImageView> icons) {
		for (int i = 0; i < icons.size(); i++) {
			iconSetDisable(icons.get(i));
		}
		GlobalParameters.deleteButton.setDisable(true);
		GlobalParameters.netButton.setDisable(true);
		GlobalParameters.meterButton.setDisable(true);
	}

	public static void open() {
		saveBeforeClose(GlobalParameters.primaryStage);

		FileChooser fileChooser = new FileChooser();
		fileChooser.setTitle("Open project");
		File file = fileChooser.showOpenDialog(GlobalParameters.primaryStage);
		GlobalParameters.fileProject = file;
		GlobalParameters.isSaved = true;
		// nastavujem nazov projektu
		setNameOfProject();
		openProject(file);
		GlobalParameters.edit.removeAll();
		// pokial uz boli vytvorene nejake cesty router, accident...tak idem
		// rovno na druhy tab
		if (!s.getRouters().isEmpty()) {
			
			GuiMethods.clearRoutersAndDistances();
			
			ByteProcessor bp = Skeletonization.stockToSkelet();
			Skeletonization.skeletonize(bp);
			//GraphCreatingMethods.createGraph();
			

			Dijkstra d = new Dijkstra(s.getGraph());
			s.setDijkstra(d);
			ControllerInitializeGui.goToMaintenanceTab();
			//load RT from file
			String path = GlobalParameters.fileProject.getParentFile().getPath();
			System.out.println("cesta k filu "+path);
			RoutingTable rt = RoutingTable.loadFromFile(path+"/"+GlobalParameters.getNameProject()+"RT.rt");			
			s.setRoutingTable(rt);
			System.out.println("RT set to stock");
			// skuska vypisov
			SearchingMethods.cellSorting();
			SearchingMethods.findDistances();
			SearchingMethods.showInfo();
				

		} else {
			System.out.println("isEmpty");
			ControllerInitializeGui.goToCreatingTab();
		}
	}

	public static void save() {
		// pokial je cesta k filenamu prazdna - musim otvorit save as
		if (GlobalParameters.fileProject == null) {
			saveAs();
			return;
		} else {
			if (GlobalParameters.isSaved) {
				return;
			} else {
				// zapisem do filu
				GlobalParameters.isSaved = true;
				writeProject(GlobalParameters.fileProject);
				setNameOfProject();
				GlobalParameters.edit.removeAll();
				GuiPainting.createZoomedCanvas();
			}
		}
	}

	public static void saveAs() {
		FileChooser fileChooser = new FileChooser();
		fileChooser.setTitle("Save project as");
		// System.out.println(pic.getId());
		File file = fileChooser.showSaveDialog(GlobalParameters.primaryStage);
		// file.createNewFile();
		GlobalParameters.fileProject = file;
		GlobalParameters.isSaved = true;
		// zapisem do filu
		writeProject(file);
		setNameOfProject();
		GlobalParameters.edit.removeAll();
		GuiPainting.createZoomedCanvas();
	}

	public static boolean windowClosedClicked(Stage stage) {
		boolean result = false;
		/*
		DialogResponse response = Dialogs.showConfirmDialog(stage,
				"Do you want to continue?", "You are closing program", "");
		if (response == DialogResponse.YES) {
			result = saveBeforeClose(stage);
		}
		return result;
*/
		Action response = Dialogs.create()
		        .owner(stage)
		        .title("")
		        .masthead("You are closing program")
		        .message("Do you want to continue?")
		        .showConfirm();

		if (response == Dialog.ACTION_YES){
			result = saveBeforeClose(stage);
		}
		return result;

	}

	private static boolean saveBeforeClose(Stage stage) {
		if (!GlobalParameters.isSaved) {
			/*
			DialogResponse response = Dialogs.showConfirmDialog(stage,
					"Do you want to save changes?", "Project was modified", "");
			if (response == DialogResponse.YES) {
				save();
				return true;
			} else if (response == DialogResponse.NO) {
			*/
			Action response = Dialogs.create()
			        .owner(stage)
			        .title("")
			        .masthead("Project was modified")
			        .message("Do you want to save changes?")
			        .showConfirm();

			if (response == Dialog.ACTION_YES){
				save();
				return true;
			}
			else if (response == Dialog.ACTION_NO){
			//vraciam true aby sa to zavrelo, ale neukladam
				return true;
			} else {
				return false;
			}
		}
		return true;
	}

	public static boolean nextStepProceed(Stage stage) {
		boolean result = false;
		/*
		DialogResponse response = Dialogs
				.showConfirmDialog(
						stage,
						"You won't be able to edit warehouse. Do you want to continue?",
						"This action will move to maintenance part", "");
		if (response == DialogResponse.YES) {
		*/
		Action response = Dialogs.create()
		        .owner(stage)
		        .title("")
		        .masthead("This action will move to maintenance part")
		        .message("You won't be able to edit warehouse. Do you want to continue?")
		        .showConfirm();

		if (response == Dialog.ACTION_YES){
		
			if (saveBeforeClose(GlobalParameters.primaryStage)) {

				GuiMethods.clearRoutersAndDistances();
				ByteProcessor bp = Skeletonization.stockToSkelet();
				Skeletonization.skeletonize(bp);

				
				
				GraphCreatingMethods.createGraph();
				GraphCreatingMethods.createDijkstraAndRT();
				
				SearchingMethods.cellSorting();
				SearchingMethods.findDistances();
				SearchingMethods.showInfo();
				
				
				
				GuiPainting.createZoomedCanvas();
				result = true;
			}
		}
		return result;
	}

	public static boolean toCreatingStepProceed(Stage stage) {
		boolean result = false;
		/*
		DialogResponse response = Dialogs
				.showConfirmDialog(
						stage,
						"All your settings of paths will be lost. Do you want to continue?",
						"This action will move to creating part", "");
		if (response == DialogResponse.YES) {
		*/
		Action response = Dialogs.create()
		        .owner(stage)
		        .title("")
		        .masthead("This action will move to creating part")
		        .message("All your settings of paths will be lost. Do you want to continue?")
		        .showConfirm();

		if (response == Dialog.ACTION_YES){
			result = true;
		}
		return result;
	}

	public static boolean isCreatingSelected() {
		if (GlobalParameters.reckCanvas.getSelectedReck() != null)
			return true;
		if (GlobalParameters.otherCanvas.getSelectedObject() != null)
			return true;
		if (GlobalParameters.accidentCanvas.getSelectedAccident() != null)
			return true;
		if (GlobalParameters.deleteButton.isSelected())
			return true;
		return false;
	}

	public static void maintenanceCanvasClicked(int xInField, int yInField,
			MouseEvent me) {
		AccidentCanvas ac = GlobalParameters.accidentCanvas;
		
		
		// pokial sa nevybera tak zvyraznim cestu a zobrazim metriku
		// pravy klik
		if (me.getButton() == MouseButton.SECONDARY) {
			// zrusim selected route a vratin
			GuiPainting.selectedRoute = -1;
			// nastav metriku v textfielde na nic
			GlobalParameters.metricTextField.setText("");

			GlobalParameters.deleteButton.setSelected(false);
			ac.setSelectedAccident(null);
			ac.paintCanvas();
			// prekresli
			GuiPainting.createZoomedCanvas();
			return;
		}
		if (GlobalParameters.deleteButton.isSelected()) {
			reckCreating(xInField, yInField, true);
		}
		// ak sa vybera accident
		if (ac.getSelectedAccident() != null) {
			// robm nejaku zmenu
		//	fieldChanged();
			reckCreating(xInField, yInField, true);

		}
		
		
		
		int pathNumber = GraphCreatingMethods.getPathNumberByClick(xInField,
				yInField);
		if (pathNumber == -1) {
			// kliklo sa niekde mimo cesty
			GlobalParameters.metricTextField.setText("");
			// zrusim zvyraznenie cesty
			GuiPainting.selectedRoute = -1;
			GuiPainting.createZoomedCanvas();
			return;
		}
		
		GuiPainting.selectedRoute = pathNumber;
		GuiPainting.showPathByNumber(pathNumber, GlobalParameters.mainCanvas,
				GlobalParameters.gc);
		// prekresli ak bola vybrata predtym ina cesta
		GuiPainting.createZoomedCanvas();

	}
	
	public static void progressBarSetVisible(boolean x){
		GlobalParameters.progressLabel.setVisible(x);
		GlobalParameters.progressRT.setVisible(x);
		GlobalParameters.cancelProgress.setVisible(x);
		
		GlobalParameters.deleteButton.setDisable(x);
		GlobalParameters.netButton.setDisable(x);
		GlobalParameters.meterButton.setDisable(x);
		GlobalParameters.metricTextField.setDisable(x);
		GlobalParameters.metricButton.setDisable(x);
		GlobalParameters.mainMaintenanceCanvas.setDisable(x);
		
		Vector<ImageView> initialIcons = ControllerInitializeGui.getInitialIcons();
			initialIcons.add(GlobalParameters.newIcon);	
			initialIcons.add(GlobalParameters.openIcon);
			initialIcons.add(GlobalParameters.toCreatingStepIcon);
			initialIcons.add(GlobalParameters.toWorkingStepIcon);
			
		if(x == true){
		GuiMethods.iconsInitialSetDisable(initialIcons);
		GlobalParameters.menuBar.setDisable(true);
		}
		else{
			GuiMethods.iconsInitialSetEnable(initialIcons);
			GlobalParameters.menuBar.setDisable(false);
		}
	}
}
