package de.tud.kom.p2psim.impl.topology.movement.vehicular.sumo.simulation.controller.xml;

import java.util.HashMap;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import de.tud.kom.p2psim.impl.topology.PositionVector;
import de.tud.kom.p2psim.impl.topology.movement.vehicular.sumo.simulation.controller.VehicleInformationContainer;

public class VehicleDataInformationHandler extends DefaultHandler {
	private boolean _next = true;
	private boolean _run = true;
	private HashMap<String, VehicleInformationContainer> _vehiclePositions = new HashMap<>();
	private double _currentStep = -1;

	private boolean _observedAreaSet = false;
	private double _startX = -1;
	private double _startY = -1;
	private double _endX = -1;
	private double _endY = -1;

	private HashMap<String, VehicleInformationContainer> _nextVehiclePositions = new HashMap<>();
	private double _nextStep = -1;

	private static final String doublePattern = "-?[0-9]*\\.?[0-9]+";
	private boolean _terminated = false;

	@Override
	public void startElement(String pUri, String pLocalName, String pQName, Attributes pAttributes)
			throws SAXException {
		if (pQName.equals("timestep")) {
			while (!_next) {
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}

			_next = false;
			String value = pAttributes.getValue("time");
			if (value.matches(doublePattern)) {
				_nextStep = Double.valueOf(value);
			}
		} else if (pQName.equals("vehicle")) {
			String id = pAttributes.getValue("id");
			String lonString = pAttributes.getValue("x");
			String latString = pAttributes.getValue("y");
			String speedString = pAttributes.getValue("speed");
			String headingString = pAttributes.getValue("angle");
			if (lonString.matches(doublePattern) && latString.matches(doublePattern) && headingString.matches(doublePattern) && speedString.matches(doublePattern) ) {
				double lon = Double.valueOf(lonString);
				double lat = Double.valueOf(latString);
				double heading = Double.valueOf(headingString);
				double speed = Double.valueOf(speedString);

				if (_observedAreaSet) {
					if (_startX <= lon && lon <= _endX && _startY <= lat && lat <= _endY) {
						_nextVehiclePositions.put(id, new VehicleInformationContainer(new PositionVector(lon - _startX, lat - _startY, 0), heading, speed, null));
					}
				} else {
					_nextVehiclePositions.put(id, new VehicleInformationContainer(new PositionVector(lon, lat, 0), heading, speed, null));
				}
			}
		}
	}

	@Override
	public void endElement(String pUri, String pLocalName, String pQName) throws SAXException {
		if (pQName.equals("timestep")) {
			_run = false;
		} else if (pQName.equals("fcd-export")) {
			while (!_next) {
				try {
					Thread.sleep(10);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
			_next = false;
			_run = false;
			_terminated = true;
		}
	}

	public void setObservedArea(double pStartX, double pStartY, double pEndX, double pEndY) {
		_startX = pStartX;
		_startY = pStartY;
		_endX = pEndX;
		_endY = pEndY;

		_observedAreaSet = true;
	}

	public boolean isTerminated() {
		return _terminated;
	}

	public HashMap<String, VehicleInformationContainer> getVehiclePositions() {
		return _vehiclePositions;
	}

	public void readNext() {
		while (_run) {
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		_vehiclePositions = _nextVehiclePositions;
		_currentStep = _nextStep;
		_nextStep = -1;
		_nextVehiclePositions = new HashMap<>();

		_run = true;
		_next = true;
	}

	public boolean isRunning() {
		return _run;
	}

	public double getStep() {
		return _currentStep;
	}
}
