<?php
require_once(dirname(__FILE__)."/../classes/class_bbox.php");
/**
 * Representing a map object, identical to the JS object in javascripts/map.js
 * @class
 */
class Map {

	private $width;
	private $height;
	private $frameName;
	private $elementName = "maps";
	private $extent;
	private $zoomFullExtentArray = array();
	private $isOverview = false;
	private $wmsArray = array();
	
	/**
	 * @destructor
	 * @param
	 */
	function __destruct() {
	}

	/**
	 * @constructor
	 * @param
	 */
	function __construct() {
	}
	
	//-------------------------------------------------------------------------
	// getter and setter
	//-------------------------------------------------------------------------
	/**
	 * @param $value Integer
	 */
	public function setWidth ($value) {
		$this->width = $value;
	}

	/**
	 * 
	 * @return 
	 */
	public function getWidth () {
		return $this->width;
	}

	/**
	 * @param $value Integer
	 */
	public function setHeight ($value) {
		$this->height = $value;
	}

	/**
	 * 
	 * @return 
	 */
	public function getHeight () {
		return $this->height;
	}

	/**
	 * @param $value String
	 */
	public function setFrameName ($value) {
		$this->frameName = $value;
	}

	/**
	 * @param $value String
	 */
	public function setElementName ($value) {
		$this->elementName = $value;
	}

	/**
	 * 
	 * @return String
	 */
	public function getFrameName () {
		return $this->frameName;	
	}
	
	public function addZoomFullExtent ($aMapbenderBbox) {
		array_push($this->zoomFullExtentArray, $aMapbenderBbox);
	}
	
	public function getZoomFullExtentArray () {
		return $this->zoomFullExtentArray;
	}
	/**
	 * @param $value String
	 */
	public function setExtent ($aMapbenderBbox) {
		$this->extent = $aMapbenderBbox;
	}

	/**
	 * 
	 * @return Mapbender_bbox 
	 */
	public function getExtent () {
		return $this->extent;	
	}
	
	/**
	 * 
	 * @return String EPSG code of the map.
	 */
	public function getEpsg () {
		return $this->extent->epsg;	
	}
	
	public function getWms ($index) {
		if (is_numeric($index)) {
			$i = intval($index, 10); 
			if ($i < count($this->wmsArray) && count($this->wmsArray) > 0 && $i >= 0) {
				return $this->wmsArray[$i];
			}
		}
		return null;
	}
	
	/**
	 * 
	 * @return 
	 */
	public function getWmsArray () {
		return $this->wmsArray;	
	}
	
	/**
	 * 
	 * @return 
	 * @param $wmsArray Object
	 */
	public function setWmsArray ($wmsArray) {
		$this->wmsArray = $wmsArray;
	}
	
	/**
	 * 
	 * @return 
	 */
	public function isOverview () {
		return $this->isOverview;
	}
	
	public function setIsOverview ($bool) {
		$this->isOverview = $bool;
	}
	
	/**
	 * @param $value Object
	 */
	public function addWms ($value) {
		array_push($this->wms, $value);
	}	


	// ------------------------------------------------------------------------
	// map manipulation
	// ------------------------------------------------------------------------

	/**
	 * Appends the WMS of another map to this map.
	 * 
	 * @param $anotherMap Map
	 */
	public function append ($anotherMap) {
		$this->wmsArray = array_merge($anotherMap->getWmsArray(), $this->wmsArray);
	}
		
	/**
	 * Merges this map with another map: Copies the map settings from the 
	 * other map and merges the WMS (keeping the settings of the other
	 * map if there are duplicates)
	 * 
	 * @param $anotherMap Map
	 */
	public function merge ($anotherMap) {
		$this->width = $anotherMap->width;
		$this->height = $anotherMap->height;
		$this->frameName = $anotherMap->frameName;
		$this->elementName = $anotherMap->elementName;
		$this->extent = $anotherMap->extent;
		$this->isOverview = $anotherMap->isOverview;
		$this->wmsArray = wms::merge(array_merge($anotherMap->getWmsArray(), $this->wmsArray));
	}

	/**
	 * Adds WMS to this map
	 * 
	 * @return 
	 */
	public function appendWmsArray ($wmsArray) {
		$this->wmsArray = array_merge($this->wmsArray, $wmsArray);
	}
	
	/**
	 * Merge WMS into this map
	 * 
	 * @return 
	 */
	public function mergeWmsArray ($wmsArray) {
		$this->wmsArray = wms::merge(array_merge($this->wmsArray, $wmsArray));
	}


	// ------------------------------------------------------------------------
	// Instantiation
	// ------------------------------------------------------------------------
	/**
	 * 
	 * @return 
	 * @param $jsMapObject Object
	 */
	public function createFromJs ($jsMapObject) {
		$arrayBBox = explode(",", $jsMapObject->extent);
		$minx = floatval($arrayBBox[0]);
		$miny = floatval($arrayBBox[1]);
		$maxx = floatval($arrayBBox[2]);
		$maxy = floatval($arrayBBox[3]);
		$srs = $jsMapObject->epsg;
		$bbox = new Mapbender_bbox($minx, $miny, $maxx, $maxy, $srs);

		$this->width = $jsMapObject->width;
		$this->height = $jsMapObject->height;
		$this->frameName = $jsMapObject->frameName;
		$this->extent = $bbox;
		
		if (isset($jsMapObject->isOverview) && $jsMapObject->isOverview == "1") {
			$this->isOverview = true;
		}

		for ($i=0; $i < count($jsMapObject->wms); $i++){
	
			$currentWms = $jsMapObject->wms[$i];
			$wms = new wms();

			//
			// set WMS data
			//
			$wms->wms_id = $currentWms->wms_id;
			$wms->wms_version = $currentWms->wms_version;
			$wms->wms_title = $currentWms->wms_title;
			$wms->wms_abstract = $currentWms->wms_abstract;
			$wms->wms_getmap = $currentWms->wms_getmap;
			$wms->wms_getfeatureinfo = $currentWms->wms_getfeatureinfo;
			$wms->wms_getlegendurl = $currentWms->wms_getlegendurl;
			$wms->wms_filter = $currentWms->wms_filter;
			$wms->gui_epsg = $currentWms->gui_epsg;
			$wms->gui_minx = $currentWms->gui_minx;
			$wms->gui_miny = $currentWms->gui_miny;
			$wms->gui_maxx = $currentWms->gui_maxx;
			$wms->gui_maxy = $currentWms->gui_maxy;
			$wms->gui_wms_mapformat = $currentWms->gui_wms_mapformat;
			$wms->gui_wms_featureinfoformat = $currentWms->gui_wms_featureinfoformat;
			$wms->gui_wms_exceptionformat = $currentWms->gui_wms_exceptionformat;
			$wms->gui_wms_opacity = $currentWms->wms_opacity;
			$wms->gui_wms_sldurl = $currentWms->gui_wms_sldurl;
			$wms->gui_wms_visible = $currentWms->gui_wms_visible;
			$wms->gui_wms_epsg = $currentWms->gui_wms_epsg;
			$wms->data_type = $currentWms->data_type;
			$wms->data_format = $currentWms->data_format;

			for ($k = 0; $k < count($currentWms->objLayer); $k++){
				// the current layer of the JSON map object
				$currentLayer = $currentWms->objLayer[$k];

				// add new layer to WMS
				$pos = $currentLayer->layer_pos;
				$parent = $currentLayer->layer_parent;
				$wms->addLayer($pos, $parent); 

				$newLayerIndex = count($wms->objLayer) - 1;
				// $newLayer is a short cut to the layer we just added
				$newLayer = $wms->objLayer[$newLayerIndex];
				
				// set layer data
				$newLayer->layer_uid = $currentLayer->layer_uid;
				$newLayer->layer_name = $currentLayer->layer_name;
				$newLayer->layer_title = $currentLayer->layer_title;
				$newLayer->layer_dataurl_href = $currentLayer->layer_dataurl_href;
				$newLayer->layer_pos = $currentLayer->layer_pos;
				$newLayer->layer_queryable = $currentLayer->layer_queryable;
				$newLayer->layer_minscale = $currentLayer->layer_minscale;
				$newLayer->layer_maxscale = $currentLayer->layer_maxscale;
				$newLayer->layer_metadataurl = $currentLayer->metadataurl;
				$newLayer->gui_layer_wms_id = $currentLayer->gui_layer_wms_id;
				$newLayer->gui_layer_status = $currentLayer->gui_layer_status;
				$newLayer->gui_layer_style = $currentLayer->gui_layer_style;
				$newLayer->gui_layer_selectable = $currentLayer->gui_layer_selectable;

				if ($this->isOverview) {
					preg_match_all("/LAYERS\=([^&]*)/", $jsMapObject->mapURL[0], $resultMatrix);
					$layerList = $resultMatrix[1][0];
					$layerListArray = explode(",", $layerList);
					$newLayer->gui_layer_visible = (in_array($currentLayer->layer_name, $layerListArray)) ? 1 : 0;
				}
				else {
					$newLayer->gui_layer_visible = $currentLayer->gui_layer_visible;
				}
				$newLayer->gui_layer_queryable = $currentLayer->gui_layer_queryable;
				$newLayer->gui_layer_querylayer = $currentLayer->gui_layer_querylayer;
				$newLayer->gui_layer_minscale = $currentLayer->gui_layer_minscale;
				$newLayer->gui_layer_maxscale = $currentLayer->gui_layer_maxscale;
				$newLayer->gui_layer_wfs_featuretype = $currentLayer->gui_layer_wfs_featuretype;

				// BEWARE THIS IS SUPER UGLY CODE
				$newLayer->layer_epsg = array();
				for ($z = 0; $z < count($currentLayer->layer_epsg); $z++) {
					$newLayer->layer_epsg[$z] = array();
					$newLayer->layer_epsg[$z]["epsg"] = $currentLayer->layer_epsg[$z]->epsg;
					$newLayer->layer_epsg[$z]["minx"] = $currentLayer->layer_epsg[$z]->minx;
					$newLayer->layer_epsg[$z]["miny"] = $currentLayer->layer_epsg[$z]->miny;
					$newLayer->layer_epsg[$z]["maxx"] = $currentLayer->layer_epsg[$z]->maxx;
					$newLayer->layer_epsg[$z]["maxy"] = $currentLayer->layer_epsg[$z]->maxy;
				}
				
				// BEWARE THIS IS SUPER UGLY CODE
				$newLayer->layer_style = array();
				for ($z = 0; $z < count($currentLayer->layer_style); $z++) {
					$newLayer->layer_style[$z] = array();
					$newLayer->layer_style[$z]["name"] = $currentLayer->layer_style[$z]->name ? $currentLayer->layer_style[$z]->name : "default";
					$newLayer->layer_style[$z]["title"] = $currentLayer->layer_style[$z]->title ? $currentLayer->layer_style[$z]->title : "default";
					$newLayer->layer_style[$z]["legendurl"] = $currentLayer->layer_style[$z]->legendurl;
					$newLayer->layer_style[$z]["legendurlformat"] = $currentLayer->layer_style[$z]->legendurlformat;
				}

			}
			array_push($this->wmsArray, $wms);
		}
		return true;
	}
	
	
	// ------------------------------------------------------------------------
	// database functions
	// ------------------------------------------------------------------------
	public static function selectMainMapByApplication ($appId) {
		return map::selectByApplication($appId, "mapframe1");
	}
	
	public static function selectOverviewMapByApplication ($appId) {
		$currentMap = map::selectByApplication($appId, "overview");
		if ($currentMap !== null) {
			$currentMap->setIsOverview(true);
		}
		return $currentMap;
	}


	// ------------------------------------------------------------------------
	// Output
	// ------------------------------------------------------------------------
	/**
	 * Returns an array of string, which are JS statements.
	 * @return String[]
	 */
	public function toJavaScript ($wmsIndex) {
		$jsCodeArray = array();

		// initialise map object
		if ($wmsIndex === null) {
			$wmsIndex = "null";
		}
		$registerMapString = "mb_registerMapObj('" . 
			$this->frameName . "', " . 
			"'maps', " . 
			$wmsIndex . ", " . 
			$this->width . ", " . 
			$this->height . ");"; 
		array_push($jsCodeArray, $registerMapString);

//		$e = new mb_notice("Map to JS: ov? " . $this->isOverview);

		// if map is overview...
		if ($this->isOverview) {
			// ...set overview flag
			$setOverviewFlagString = "mb_mapObj[mb_mapObj.length-1].isOverview = true;";
			array_push($jsCodeArray, $setOverviewFlagString);
		}
		
		// set width
		$setMapframeWidth = "document.getElementById('" . $this->frameName . "')." . 
			"style.width = " . $this->width . ";";
		array_push($jsCodeArray, $setMapframeWidth);

		// set height
		$setMapframeHeight = "document.getElementById('" . $this->frameName . "')." . 
			"style.height = " . $this->height . ";";
		array_push($jsCodeArray, $setMapframeHeight);

		// calculate extent
		$calcExtentString = "mb_calculateExtent('" . 
			$this->frameName . "', " .
			$this->extent->min->x . ", " . 
			$this->extent->min->y . ", " . 
			$this->extent->max->x . ", " . 
			$this->extent->max->y . ");"; 
		array_push($jsCodeArray, $calcExtentString);
		return $jsCodeArray;
	}


	// ------------------------------------------------------------------------
	// PRIVATE FUNCTIONS
	// ------------------------------------------------------------------------
	
	private static function selectByApplication ($appId, $frameName) {
		// find the mapframe in the application elements...
		$sql = "SELECT * FROM gui_element WHERE fkey_gui_id = $1 AND " . 
				"e_id = $2 AND e_public = 1 LIMIT 1";
		$v = array($appId, $frameName);
		$t = array('s', 's');
		$res = db_prep_query($sql,$v,$t);
		$row = db_fetch_array($res);
		
		// if found...
		if ($row) {
			$currentMap = new Map();

			// use settings from database
			$currentMap->setWidth($row["e_width"]);
			$currentMap->setHeight($row["e_height"]);
			$currentMap->setFrameName($row["e_id"]);
			
			// get the WMS 
			$wmsArray = wms::selectMyWmsByApplication($appId);
			
//			$e = new mb_notice("WMS in this map: " . implode(",", $wmsArray));
			
			// if this is the overview, find the WMS index and 
			// reset the WMS array
			// BEWARE, SUPER UGLY CODE AHEAD!!
			// (BUT THERE IS NO OTHER WAY TO DO IT)
			if (strpos($row["e_src"], "mod_mapOV.php?wms") !== false) {
//				$e = new mb_exception("guess this is the OV");
				$pattern = "/[\.\/a-zA-Z_]*\?wms=([0-9]*)[^0-9]*/";
				$ovIndex = preg_replace($pattern, "\$1", $row["e_src"]);
//				$e = new mb_exception("OV index: " . $ovIndex);
				if (!$ovIndex) {
					$ovIndex = 0;
				}
				$wmsArray = array($wmsArray[$ovIndex]);	
//				$e = new mb_notice("WMS in this map (corrected): " . implode(",", $wmsArray));
			}
			else {
//				$e = new mb_exception("guess this is NOT the OV");
			}

			$currentMap->wmsArray = $wmsArray;
			
			// EXTENT
			$minx = $wmsArray[0]->objLayer[0]->layer_epsg[0]["minx"];
			$miny = $wmsArray[0]->objLayer[0]->layer_epsg[0]["miny"];
			$maxx = $wmsArray[0]->objLayer[0]->layer_epsg[0]["maxx"];
			$maxy = $wmsArray[0]->objLayer[0]->layer_epsg[0]["maxy"];
			$epsg = $wmsArray[0]->objLayer[0]->layer_epsg[0]["epsg"];
			$mapExtent = new Mapbender_bbox($minx, $miny, $maxx, $maxy, $epsg);
			$currentMap->setExtent($mapExtent);
			return $currentMap;			
		}
		else {
			return null;
		}
	}
	

}
?>