<?php

class Kml
{

	private $kml = NULL;
	private $waypoints = array();
	private $tracks = array();

	public function __construct($path)
	{
		$xml = substr($path, -4) == '.kmz' ? $this->getKmzContent($path) : file_get_contents($path);
		$xml = str_replace(array('<gx:', '</gx:'), array('<gx', '</gx'), $xml);

		$this->kml = new DOMDocument;
		$this->kml->loadXML($xml);

		foreach ($this->get($this->kml, 'Placemark') as $placemark) {
			if ($this->has($placemark, 'Point')) {
				$latlngs = $this->getCoords($placemark);
				$this->waypoints[] = array(
					'name' => trim($this->getValue($placemark, 'name')),
					'description' => trim($this->getValue($placemark, 'description')),
					'when' => date('c', strtotime($this->getValue($placemark, 'when'))),
					'latlng' => $latlngs[0],
				);
			}

			if ($this->has($placemark, 'LineString')) {
				$this->tracks[] = array(
					'name' => trim($this->getValue($placemark, 'name')),
					'description' => trim($this->getValue($placemark, 'description')),
					'latlng' => $this->getCoords($placemark),
				);
			}

			if ($this->has($placemark, 'gxMultiTrack')) {
				$this->tracks = $this->getTracksGX($placemark);
			}
		};
	}

	public function getName()
	{
		return $this->getValue($this->kml, 'name') ? strval($this->getValue($this->kml, 'name')) : 'Track KML';
	}

	public function getDescription()
	{
		return $this->getValue($this->kml, 'description') ? strval($this->getValue($this->kml, 'description')) : '';
	}

	public function getTime()
	{
		return $this->getValue($this->kml, 'when') ? date('c', strtotime($this->getValue($this->kml, 'when'))) : date('c');
	}

	public function getWaypoints()
	{
		return $this->waypoints;
	}

	public function getTracks()
	{
		return $this->tracks;
	}

	private function has($src, $tagName)
	{
		return $this->get($src, $tagName)->length > 0;
	}

	private function get($src, $tagName)
	{
		return $src->getElementsByTagName($tagName);
	}

	private function getValue($src, $tagName)
	{
		foreach ($src->getElementsByTagName($tagName) AS $value) {
			return $value->nodeValue;
		}
	}

	private function getCoords($src)
	{
		foreach ($src->getElementsByTagName('coordinates') AS $value) {
			$result = array();
			$coords = $value->nodeValue;
			$coords = str_replace(array(" ", "\n", "\r", "\t"), ' ', $coords);

			// multi-space
			$pr = '(\s{2,})';
			$rep = ' ';
			$coords = preg_replace($pr, $rep, $coords);

			$coords = explode(' ', trim($coords));

			foreach ($coords as $coord) {
				$tmp = explode(',', $coord);
				$result[] = array(
					'lat' => $tmp[1],
					'lng' => $tmp[0],
					'alt' => $tmp[2],
				);
			}

			return $result;
		}

		return array();
	}

	private function getTracksGX($placemark)
	{
		$result = array();
		foreach ($placemark->getElementsByTagName('gxTrack') AS $gxTrack) {
			$track = array();
			foreach ($gxTrack->getElementsByTagName('gxcoord') AS $value) {
				$coords = $value->nodeValue;
				$coords = str_replace(array(" ", "\n", "\r", "\t"), ' ', $coords);

				// multi-space
				$pr = '(\s{2,})';
				$rep = ' ';
				$coords = preg_replace($pr, $rep, $coords);

				$tmp = explode(' ', trim($coords));

				$track[] = array(
					'lat' => $tmp[1],
					'lng' => $tmp[0],
					'alt' => $tmp[2],
				);
			}

			$result[] = array(
				'name' => '',
				'description' => '',
				'latlng' => $track,
			);
		}

		return $result;
	}

	private function getKmzContent($path)
	{
		$zip = zip_open($path);
		if (!$zip) {
			App::error404();
		}

		$zip_entry = zip_read($zip);

		if (zip_entry_name($zip_entry) != 'doc.kml') {
			App::error404();
		}


		if (zip_entry_open($zip, $zip_entry, "r")) {
			$buf = zip_entry_read($zip_entry, zip_entry_filesize($zip_entry));
			zip_entry_close($zip_entry);
			zip_close($zip);

			return $buf;
		}

		App::error404();
	}

}
