<?php

/**
 * To convert a gpx file:
 * 1. Add file <file_name>.gpx to geo/ folder
 * 2. Assign file to project: UPDATE projects SET geofile = '<file_name>' WHERE id_project = <id_project>;
 */
class Converter extends PhpObject {
	
	public function __construct() {
		parent::__construct(__CLASS__, Settings::DEBUG);
	}
	
	public function convertToGeoJson($sFileName) {
		$oGpx = new Gpx($sFileName);
		$oGeoJson = new GeoJson($sFileName);
		
		$oGeoJson->setTracks($oGpx->getTracks());
		$oGeoJson->saveFile();
	}
	
	public static function isGeoJsonValid($sFileName) {
		$bResult = false;
		$sGeoJsonFilePath = Geo::getFilePath($sFileName, GeoJson::EXT);
		if(file_exists($sGeoJsonFilePath)) {
			if(filemtime($sGeoJsonFilePath) > filemtime(Geo::getFilePath($sFileName, Gpx::EXT))) $bResult = true;
		}
		return $bResult;
	}
}

class Geo extends PhpObject {
	
	const GEO_FOLDER = 'geo/';
	
	protected $asTracks;
	protected $sFilePath;
	
	public function __construct($sFileName) {
		parent::__construct(__CLASS__, Settings::DEBUG);
		$this->sFilePath = self::getFilePath($sFileName, static::EXT);
		$this->asTracks = array();
	}
	
	public static function getFilePath($sFileName, $sExt) {
		return self::GEO_FOLDER.$sFileName.$sExt;
	}
}

class Gpx extends Geo {

	const EXT = '.gpx';
	
	public function __construct($sFileName) {
		parent::__construct($sFileName);
		$this->parseFile();
	}
	
	public function getTracks() {
		return $this->asTracks;
	}
	
	private function parseFile() {
		$oXml = simplexml_load_file($this->sFilePath);
		foreach($oXml->trk as $aoTrack) {
			$asTrack = array(
				'name'	=> (string) $aoTrack->name,
				'desc'	=> str_replace("\n", '', ToolBox::fixEOL((strip_tags($aoTrack->desc)))),
				'color'	=> (string) $aoTrack->extensions->children('gpxx', true)->TrackExtension->DisplayColor,
				'points'=> array()
			);
			
			foreach($aoTrack->trkseg as $asSegment) {
				foreach($asSegment as $asPoint) {
					$asTrack['points'][] = array(
						'lon' => (float) $asPoint['lon'],
						'lat' => (float) $asPoint['lat'],
						'ele' => (int) $asPoint->ele
					);
				}
			}
			$this->asTracks[] = $asTrack;
		}
	}
}

class GeoJson extends Geo {
	
	const EXT = '.geojson';
	
	public function __construct($sFileName) {
		parent::__construct($sFileName);
	}
	
	public function setTracks($asTracks) {
		$this->asTracks = $asTracks;
	}
	
	public function saveFile() {
		$sContent = json_encode($this->getGeoJson());
		file_put_contents($this->sFilePath, $sContent);
	}
		
	private function getGeoJson() {
		$asTracks = array('features'=>array());
		foreach($this->asTracks as $asTrackProps) {
			
			//Color mapping
			switch($asTrackProps['color']) {
				case 'DarkBlue':	$sType = 'main'; break;
				case 'Magenta':		$sType = 'off-track'; break;
				case 'Red':			$sType = 'hitchhiking'; break;
				default: 			continue 2; //discard tracks
			}
			
			$asTrack = array(
				'type'	=> 'Feature',
				'properties' => array(
					'name'			=> $asTrackProps['name'],
					'type'			=> $sType,
					'description'	=> $asTrackProps['desc']
				),
				'geometry'		=> array(
					'type'			=> 'LineString',
					'coordinates'	=> array()
				)
			);
			
			foreach($asTrackProps['points'] as $asPoint) {
				$asTrack['geometry']['coordinates'][] = array_values($asPoint);
			}
			$asTracks['features'][] = $asTrack;
		}
		
		return $asTracks;
	}
}