package cz.vutbr.feec.stockElements;

import java.util.Vector;

import ij.process.ByteProcessor;
import cz.vutbr.feec.graph.Path;
import cz.vutbr.feec.graph.Router;
import cz.vutbr.feec.graph.RoutingTable;
import cz.vutbr.feec.libraryClasses.GraphCreatingMethods;
import cz.vutbr.feec.libraryClasses.GuiMethods;
import cz.vutbr.feec.libraryClasses.SearchingMethods;
import cz.vutbr.feec.libraryClasses.Skeletonization;
import cz.vutbr.feec.project.GlobalParameters;

public class Accident {
	private Path path;
	private int costBefore;
	private AccidentCell cell;
	private Stock s = Stock.getInstance();
	private int pathNumber;
	private boolean moreAccidentsOnPath = false;
	private Vector<CoridorCell> affectedCells = new Vector<>();

	// spravim konstruktor v ktorom sa vytvoria vsetky tieto parametre
	public Accident(AccidentCell c) {
		setCell(c);
		c.setAccident(this);
		// najskor musim identifikovat cestu
		pathNumber = GraphCreatingMethods.getPathNumberByClick(c.getX(),
				c.getY());
		path = s.getPaths().get(pathNumber);
		costBefore = path.getCost();
		// rovno mozem zmenit
	}

	public Path getPath() {
		return path;
	}

	public void setPath(Path path) {
		this.path = path;
	}

	public void setCostBefore() {
		path.setCost(costBefore);
		path.getFirstRouter().setCost(path.getSecondRouter(), costBefore);
		path.getSecondRouter().setCost(path.getFirstRouter(), costBefore);
		// treba prepocitat RT
		RoutingTable rt = new RoutingTable(s.getGraph());
		s.setRoutingTable(rt);

	}

	public void setCostToInfinty() {
		int infinity = GlobalParameters.INFINITY;
		path.setCost(infinity);
		path.getFirstRouter().setCost(path.getSecondRouter(), infinity);
		path.getSecondRouter().setCost(path.getFirstRouter(), infinity);
		// treba prepocitat RT
		RoutingTable rt = new RoutingTable(s.getGraph());
		s.setRoutingTable(rt);
		// TODO Auto-generated method stub

	}

	public void returnPath() {
		// ak je viac nehod na ceste tak znova prepocitavam
		if (moreAccidentsOnPath) {
		
			recalculatePath();
			// prepocitat ostatne dotknute bunky
			SearchingMethods.findDistances();
			//recalculateAffectedCells();
			return;
		}
		// ak bola iba jedna tak vraciam do povodneho stavu
		for (int i = 0; i < path.getPath().size(); i++) {
			AbstractStockCell c = path.getPath().get(i);
			// prepisem konkretne indexy vectoru
			c.clearRouters();
			c.addDistance(GraphCreatingMethods.getMetricToFirstRouter(i));
			c.addRouter(path.getFirstRouter());
			c.addRouter(path.getSecondRouter());
			c.addDistance(GraphCreatingMethods.getMetricToSecondRouter(
					pathNumber, i));
		}
		// recalculovat ostatne bunky
		
		//recalculateAffectedCells();

		SearchingMethods.findDistances();
	}

	public void recalculatePath() {
		int accidentIndex1 = 0;
		int accidentIndex2 = 0;
		// cyklus zacina od prveho routra, resp od prvej bunky cesty
		for (int i = 0; i < path.getPath().size(); i++) {
			System.out.println("prvy cyklus buniek");
			// musim porovnat bunky s accident bunkou
			AbstractStockCell c = path.getPath().get(i);
			if (s.getFieldIndex(c.getX(), c.getY()).getClass() == AccidentCell.class) {
				// nedorucitelna . tu je nehoda moze byt hocijaka, nie len tato
				// konkretna
				// zacnem pocitat z druhej strany od secondroutra,
				// aby som zamedzil chybe s dvoma a viac nehodami na ceste
				accidentIndex1 = i;
				break;
			} else {
				try {

					c.getClosestDistances().remove(1);// vymazavam secondRouter
					c.getClosestRouters().remove(1);
				} catch (Exception e) {
					if(moreAccidentsOnPath){
						//pridam firstRouter
						c.getClosestDistances().removeAllElements();
						c.getClosestRouters().removeAllElements();
						c.addRouter(path.getFirstRouter());
						c.addDistance(GraphCreatingMethods.getMetricToFirstRouter(i));
					}
					// moze sa stat ze je viacej poruch na
					// rovnakej ceste a uz je vymazany druhy router
					
				}
			}
		}
		// teraz opacne od secondRoutra nastavim ho ako firstRouter
		System.out.println("pathSize");
		int index = path.getPath().size();
		index--;
		// berem poslednu bunku
		AbstractStockCell c = path.getPath().get(index);
		System.out.println("getPaThSize");
		while (s.getFieldIndex(c.getX(), c.getY()).getClass() != AccidentCell.class) {
			System.out.println("nastavujem druhu cast cesty");
			try {

				Router r = c.getClosestRouters().get(1);
				int d = c.getClosestDistances().get(1);// vymazavam firstRouter
				c.getClosestDistances().removeAllElements();
				c.getClosestRouters().removeAllElements();
				c.addDistance(d);
				c.addRouter(r);
				index--;
				c = path.getPath().get(index);
			} catch (Exception e) {
				if(moreAccidentsOnPath){
					//pridam secondRouter
					//pridam firstRouter
					c.getClosestDistances().removeAllElements();
					c.getClosestRouters().removeAllElements();
					c.addRouter(path.getSecondRouter());
					c.addDistance(GraphCreatingMethods.getMetricToSecondRouter(pathNumber, index));
					
					
					moreAccidentsOnPath = false;
				}
				index--;
				c = path.getPath().get(index);
			}
		}
		accidentIndex2 = index;
		/*
		 * for (int i = path.getPath().size(); i < 0; i--) { AbstractStockCell c
		 * = path.getPath().get(i); if (s.getFieldIndex(c.getX(),
		 * c.getY()).getClass() == AccidentCell.class) { // nedorucitelna . tu
		 * je nehoda accidentIndex2 = i;
		 * 
		 * break; } else {
		 * 
		 * Router r = c.getClosestRouters().get(1); int d =
		 * c.getClosestDistances().get(1);// vymazavam firstRouter
		 * c.getClosestDistances().removeAllElements();
		 * c.getClosestRouters().removeAllElements(); c.addDistance(d);
		 * c.addRouter(r);// secondby sa mal premiestnit // na prvu poziciu } }
		 */
		// este by bolo vhodne skontrolovat ostatne bunky na ceste ci tam
		// nahodou nie su zaseknute
		try {

			for (int i = accidentIndex1 + 1; i < accidentIndex2; i++) {
				c = path.getPath().get(i);
				c.getClosestDistances().removeAllElements();
				c.getClosestRouters().removeAllElements();
				// pridam do atributov ze tu je viac nehod na ceste
				moreAccidentsOnPath = true;
			}
		} catch (Exception e) {
			// TODO: handle exception
		}
		
		//recalculateAffectedCells();
		SearchingMethods.findDistances();
	}

	private void recalculateAffectedCells() {
		// prepocitat ostatne dotknute bunky
		ByteProcessor bp = Skeletonization.stockToSkelet();
		// ak uz je vytvorene pole nech to nemusim cele prehladavat znova
		if (affectedCells.isEmpty()) {
			// k tomu potrebujem zmenit binp

			// pre vsetky coridorCells, ale ktore maju tieto dva routre
			CoridorCell[] cells = (CoridorCell[]) GlobalParameters.allCoridorCells
					.toArray(new CoridorCell[GlobalParameters.allCoridorCells
							.size()]);
			for (CoridorCell coridorCell : cells) {
				if (coridorCell.getClosestRouters().contains(
						path.getFirstRouter())
						&& coridorCell.getClosestRouters().contains(
								path.getSecondRouter())) {
					// musim najskor vymazat routre a vzdialenosti
					coridorCell.clearRouters();
					SearchingMethods.findDistance(coridorCell, bp);
					affectedCells.add(coridorCell);
				}
			}
		} else {
			for (int i = 0; i < affectedCells.size(); i++) {
				affectedCells.get(i).clearRouters();
				SearchingMethods.findDistance(affectedCells.get(i), bp);
			}
		}
	}

	public boolean isMoreAccidentsOnPath() {
		return moreAccidentsOnPath;
	}

	public void setMoreAccidentsOnPath(boolean moreAccidentsOnPath) {
		this.moreAccidentsOnPath = moreAccidentsOnPath;
	}

	public AccidentCell getCell() {
		return cell;
	}

	public void setCell(AccidentCell cell) {
		this.cell = cell;
	}

}
