function PushpinGenerator() {
	var owner = this;

	owner.supportedEvents =
		[
			"battery_state_charging",
			"battery_state_discharging",
			"battery_state_low_battery",
			"low_battery", //todo remove later
			"check_in",
			"crash",
			"device_state_reboot",
			"device_state_start",
			"device_state_stop",
			"driving_behavior", //todo
			"external_antenna_cut",
			"external_antenna_ok",
			"external_antenna_unknown",
			"external_power_state_0",
			"external_power_state_1",
			"gprs_on",
			"ignition_0",
			"ignition_1",
			"jamming",
			"job_state_complete",
			"job_state_incomplete",
			"low_external_battery",
			"obd_report",
			"sos",
			"temperature",
			"temperature_high",
			"temperature_low"
		];

	owner.createEventPushpin = function (event) {
		return new L.Icon({
			iconUrl: './images/pushpins/pushpin_event_' + event + '.png',
			iconSize: new L.Point(41, 81),
			iconAnchor: new L.Point(21, 77),
			popupAnchor: new L.Point(0, -81)
		});
	};

	owner.createReportPushpin = function (properties) {
		var color;
		if (properties.precision == -1)
			return new L.Icon({
				iconUrl: './images/pushpins/pushpin_invalid.png',
				iconSize: new L.Point(19, 31),
				iconAnchor: new L.Point(9, 25),
				popupAnchor: new L.Point(0, -31)
			});
		else if (parseFloat(properties.speed).toFixed(0) == 0)
			return new L.Icon({
				iconUrl: './images/pushpins/pushpin_blue_rectangle.png',
				iconSize: new L.Point(19, 31),
				iconAnchor: new L.Point(10, 27),
				popupAnchor: new L.Point(0, -26)
			});
		if (properties.speed <= 5)
			color = "blue";
		else if (properties.speed < 60)
			color = "green";
		else if (properties.speed < 100)
			color = "orange";
		else if (properties.speed < 130)
			color = "purple";
		else
			color = "red";

		var angle;
		if (properties.heading >= 315 || properties.heading < 45)
			angle = 0;
		else if (properties.heading >= 45 && properties.heading < 135)
			angle = 90;
		else if (properties.heading >= 135 && properties.heading < 225)
			angle = 180;
		else
			angle = 270;

		if (angle == 0 || angle == 180)
			return new L.Icon({
				iconUrl: './images/pushpins/pushpin_' + color + '_' + angle + '.png',
				iconSize: new L.Point(31, 19),
				iconAnchor: new L.Point(27, 10),
				popupAnchor: new L.Point(-17, -10)
			});
		else if (angle == 90 || angle == 270)
			return new L.Icon({
				iconUrl: './images/pushpins/pushpin_' + color + '_' + angle + '.png',
				iconSize: new L.Point(19, 31),
				iconAnchor: new L.Point(10, 27),
				popupAnchor: new L.Point(0, -26)
			});
	};

	this.get_pushpin = function (feature, latlng) {
		var properties = feature.properties;
		var title = properties && jQuery.parseJSON(properties.name) + "\n" + (new Date(properties.date * 1000).toLocaleString());
		if ($.inArray(properties.reportType + "_" + properties.reportValue, owner.supportedEvents) != -1) {
			this.marker = new L.Marker(latlng,
			   {
			   	icon: owner.createEventPushpin(properties.reportType + "_" + properties.reportValue),
			   	title: title
			   });
		}
		else if ($.inArray(properties.reportType, owner.supportedEvents) != -1) {
			this.marker = new L.Marker(latlng,
				{
					icon: owner.createEventPushpin(properties.reportType),
					title: title
				});
		}
		else {
			this.marker = new L.Marker(latlng,
			   {
			   	icon: owner.createReportPushpin(properties),
			   	title: title
			   });
		}
		this.marker.number = properties.number;
		return this.marker;
	}
}