//declaration and initialization, configuration 
var map, objMyKMLs, objMyTopFeatures, objBusRoutes, objKMLTileReq, objSrcMarker, objAutoRefresh, markers, SGTSMap, SGBaseMap1, nav;
var objprivateTransport,
    intBStopZoom=4,
    intTotalZoom=5,
    intCenterX=103.82325651855469,
    intCenterY=1.331854052734375,
    //intXPlus=0.0163,//0.012,       //original values
    //intYPlus=0.00612,//0.0045,    //original values

    intTimer= 300000;//in miliseconds
    intImgReloadAttemp=3,
	privateTransportlayer="topmostPrivateTransport",
    //strERPURL= NumOfKMLFiles + "Files/" + "ERP/erp-kml-",                       //for ERP
    //strTIURL= NumOfKMLFiles + "Files/" + "TI/trafficInc-kml-",                  //for Traffic Incidents
    //strTraffCamURL= NumOfKMLFiles + "Files/" + "trafficCam/trafficCam-kml-",    //for Traffic Cameras
    strImgURL='',
    //strMapServerURL="/fcgi/tilecache.fcgi?",//production
    //strMapServerURL="/cgi-bin/tilecache.cgi?",//development
    strMapServerURL="/tilecache/",//tilecache protocol
    strWMSMapServerURL="/mapapp/tilecache_RCL/";//Isaac: converted into tilecache protocol due to python issue @ 20090309
    arrTileBounds = new Array(103.60237668500001, 1.233206, 104.1028941, 1.47733325),     
    arrOriBounds= new Array(-180, -90, 180, 90),
    //arrResolution= new Array(0.0006866455078125, 0.000171661376953125, 4.291534423828125e-005, 2.1457672119140625e-005, 1.0728836059570313e-005, 5.3644180297851563e-006);
    arrResolution= new Array(0.0006866455078125, 0.000171661376953125, 4.291534423828125e-005, 2.1457672119140625e-005, 1.0728836059570313e-005);

//setting the X and Y coordinates depending on number of files
	  var intXPlus;
    var intYPlus;
    var strERPURL;
    var strTIURL;
    var strTraffCamURL;
    var NumOfKMLFiles;
	var strPGSURL;
//end of declaration and initialization, configuration

function readSystemConfig(url){
	loadIMSXML(url);		
	readIMSConfigMessages();
}

function loadIMSXML(url) {
	
	xmlhttp=null;
	if (window.XMLHttpRequest){// code for IE7, Firefox, Mozilla, etc.
		xmlhttp=new XMLHttpRequest();
	}else if (window.ActiveXObject){// code for IE5, IE6
		xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
	}
	if (xmlhttp!=null){
		xmlhttp.onreadystatechange=onResponse;
		xmlhttp.open("GET", url, false);
		xmlhttp.send(null);		
	 }else {
		alert("Your browser does not support XMLHTTP.");
	  }
}

function readIMSConfigMessages()
 {	
	IMSTag = xmlhttp.responseXML.documentElement.getElementsByTagName("MapData");
	intXPlus = (IMSTag[0].getElementsByTagName("XPlus"))[0].childNodes[0].nodeValue;

	intYPlus = (IMSTag[0].getElementsByTagName("YPlus"))[0].childNodes[0].nodeValue;

	NumOfKMLFiles = (IMSTag[0].getElementsByTagName("NumOfKMLFiles"))[0].childNodes[0].nodeValue;	

	
	LocationTag = xmlhttp.responseXML.documentElement.getElementsByTagName("KMLLocation");
	strERPURL = (LocationTag[0].getElementsByTagName("ERP"))[0].childNodes[0].nodeValue;
	
	strTIURL = (LocationTag[0].getElementsByTagName("TrafficIncident"))[0].childNodes[0].nodeValue;

	strTraffCamURL =(LocationTag[0].getElementsByTagName("TrafficCamera"))[0].childNodes[0].nodeValue;
	
	strPGSURL =(LocationTag[0].getElementsByTagName("PGS"))[0].childNodes[0].nodeValue;
	 
}

function onResponse()  
{
	if(xmlhttp.readyState!=4) return;
	if(xmlhttp.status!=200){
	  alert("Problem retrieving XML data");
	  return;
	}		
}

function marker(lat,long,zoom){
	
	//objSrcMarker.showOnMap(zoom,103.87501,1.2937332+0.00005);
	 objSrcMarker.showOnMap(zoom,lat,long);
}

function init(strMapGuideIP,strWMSMapServerIP,strPage, strMapImgURL,flagRedirect){
    readSystemConfig('../IMSConfig.xml');
   
    //redefine URL to add in Magnolia path

    strImgURL       = strMapImgURL;
    
    //avoid pink tiles
    OpenLayers.IMAGE_RELOAD_ATTEMPTS = intImgReloadAttemp;
    OpenLayers.Util.alphaHack = function() { return false; }
    
    // define custom map zoom event listeners to change base map
    function mapZoomEvent(event) {
        objAutoRefresh.Refresh();
    }
    
    // define custom map "move end" event listener to load bus stops
    function mapMoveEvent(event) {
        objAutoRefresh.ResetCounter();
//        if(!(typeof(popup) != "undefined" && popup != null))
	        objMyKMLs.popupIndicator++;
    }
    
    function mapDragStart(event) {
    	map.div.style.cursor = "url(/mapapp/scripts/map/theme/default/img/closedhand.cur), default";
    }
    
    function mapDragEnd(event) {
    	map.div.style.cursor = "url(/mapapp/scripts/map/theme/default/img/openhand.cur), default";
    }

    function mapMouseOver(event) {
    	map.div.style.cursor = "url(/mapapp/scripts/map/theme/default/img/openhand.cur), default";
    }

    function mapMouseOut(event) {
    	map.div.style.cursor = "url(/mapapp/scripts/map/theme/default/img/openhand.cur), default";
    }

    maxExt = new OpenLayers.Bounds(arrOriBounds[0],arrOriBounds[1],arrOriBounds[2],arrOriBounds[3]); 
    map_opts = {
    'controls' : new Array(
            //new OpenLayers.Control.KeyboardDefaults(),
            new OpenLayers.Control.Navigation(),
            new OpenLayers.Control.PanZoomBar()
        ),
    'maxExtent' : maxExt,
    'resolutions': arrResolution,
    'maxResolution': arrResolution[0],
    'numZoomLevels': intTotalZoom,
    'eventListeners': {
                "zoomend": mapZoomEvent,
                "moveend": mapMoveEvent}
		//"dragstart": mapDragStart,
		//"dragend": mapDragEnd,
		//"mouseover": mapMouseOver,
		//"mouseout": mapMouseOut}
    };

    map = new OpenLayers.Map( $('map'),map_opts);    

    // isaac yong @ 20081111 /added
    strMapURL = "http://" + strMapGuideIP + strMapServerURL;
    strWMSMapURL = "http://" + strWMSMapServerIP + strWMSMapServerURL;
    
    //conf for WMS layer
	/*
    SGBaseMap1 = new OpenLayers.Layer.WMS("SGBaseMap1",[strMapURL],{layers:'SGBaseMap1'},
            {'buffer':0,'displayInLayerSwitcher':true,
            'attribution': '<a href=\"http://www.sla.gov.sg/\"><img border=\"0\" src=\"/mapapp/images/SLA_logo.gif\" /></a>'});
    */
    //conf for TileCache layer, to enable this.
    SGBaseMap1 = new OpenLayers.Layer.TileCache("SGBaseMap1",[strMapURL],
            "SGBaseMap1",{'format':'image/gif','buffer':0,'displayInLayerSwitcher':false,
            'attribution': '<a href=\"http://www.sla.gov.sg/\"><img border=\"0\" src=\"http://' + strMapImgURL + '/SLA_logo.gif\" /></a>',
            'resolutions': arrResolution});
    
    
    SGTSMap = new OpenLayers.Layer.TileCache("SGRCLMap",[strWMSMapURL],
            "SGRCLMap",{'format':'image/gif','buffer':0,'displayInLayerSwitcher':false,
	    'opacity': 0.5, 'isBaseLayer': false});
	
    SGTSMap.setVisibility(false);
    map.addLayers([SGBaseMap1,SGTSMap]);
    
    //map.addControl(new OpenLayers.Control.PanZoomBar());            
    map.addControl(new OpenLayers.Control.ScaleLine());            
    map.addControl(new OpenLayers.Control.MousePosition());
    map.addControl(new OpenLayers.Control.Attribution());
	map.addControl((nav = new OpenLayers.Control.NavigationHistory()));
    //map.addControl(new OpenLayers.Control.LayerSwitcher());
    map.div.style.cursor = "url(/mapapp/scripts/map/theme/default/img/openhand.cur), default";

    //objects initialization
    objMyKMLs     = new objKMLs(); 
    objSrcMarker  = new SearchMarker();
    objprivateTransport  = new privateTransport(strERPURL, strTraffCamURL, strTIURL, NumOfKMLFiles);           //to call PrivateTransportSystem
    objAutoRefresh = new autoRefresh();
    //end of objects initialization
    
    //add markers layer after top most layer is created, so that markers will always on top.
    markers = new OpenLayers.Layer.Markers( "Markers", {'calculateInRange': function() { return true; }});
    map.addLayer(markers);
    
    // isaac yong @ 20081111 /modded
    map.setBaseLayer(SGBaseMap1);
    objMyKMLs.setTopMostLayer(markers);
    
    //Mod by Isaac @ 20081245 for autoRefresh object;
    objAutoRefresh.Start(intTimer);
    
    //if (!map.getCenter()) map.zoomToMaxExtent();
    map.moveTo(new OpenLayers.LonLat(intCenterX,intCenterY),0);
    if(flagRedirect=='redirect'){
    	parent.showframe.document.getElementById("cb_ERP").click();
    	//objprivateTransport.showERP();
    	//alert('show erp');
    }
}

// -- for private transport layer -- //
function privateTransport(strERPURL, strTraffCamURL, strTIURL, NumOfKMLFiles)
{
    this.strERPURL = strERPURL;
    this.strTraffCamURL = strTraffCamURL;
    this.strTIURL = strTIURL;    
    this.NumOfKMLFiles = NumOfKMLFiles; //20 files
    this.kmlLayer = new Array();    
	this.strPGSURL = strPGSURL;
    
    var strURL = new Array();  
    var privateTransportFeatures;
    
    //creating private transport layer
    privateTransportFeatures =  new objFeatures(objMyKMLs.createTopMostLayer(privateTransportlayer));
    privateTransportFeatures.srcMarker=objSrcMarker;
     
    //to show ERP
    this.showERP = function()
    {    
        strURL = new Array();
        for(var i = 0; i<NumOfKMLFiles; i++)
        {   
            strURL[i] = strERPURL + i + ".kml"; 
            //if(!privateTransportFeatures.containsFeatureKey(strURL[i]))
            //{
                privateTransportFeatures.addFeature(strURL[i],strURL[i],true);
                privateTransportFeatures.enableFeature(strURL[i]);
            //}           
        }          
    }   
      //to remove ERP  
      this.removeERP = function()
        {    
            strURL = new Array();           
            for(var i = 0; i<NumOfKMLFiles; i++)
            {   
                strURL[i] = strERPURL + i + ".kml"; 
                privateTransportFeatures.disableFeature(strURL[i]);
            }
            removePopup("erp");
        }    
        
        //to show traffic incidents
        this.showTrafficIncidents = function()
        {    
            strURL = new Array();                
            for(var i = 0; i<NumOfKMLFiles; i++)
            {   
                strURL[i] = strTIURL + i + ".kml"; 
                privateTransportFeatures.addFeature(strURL[i],strURL[i],true);
                privateTransportFeatures.enableFeature(strURL[i]);
             }   
        }    
        
		    this.showTrafficIncidentsForceRefresh = function()
        {    
            strURL = new Array();                
            for(var i = 0; i<NumOfKMLFiles; i++)
            {   
                strURL[i] = strTIURL + i + ".kml"; 
                privateTransportFeatures.addFeature(strURL[i],strURL[i],true);
                privateTransportFeatures.enableFeature(strURL[i],true);
             }   
        }        		
        
        //to remove traffic incidents
        this.removeTrafficIncidents = function()
        {               
            strURL = new Array();           
            for(var i = 0; i<NumOfKMLFiles; i++)
            {   
                strURL[i] = strTIURL + i + ".kml";  
                privateTransportFeatures.disableFeature(strURL[i]);
                
            }
            removePopup("incident");
        }    
        
        //to show traffic cameras
       this.showTrafficCam = function()
        {    
            strURL = new Array();                
            for(var i = 0; i<NumOfKMLFiles; i++)
            {   			
			 	strURL[i] = strTraffCamURL + i + ".kml"; 
				// if(!privateTransportFeatures.containsFeatureKey(strURL[i]))
           		//{
                	privateTransportFeatures.addFeature(strURL[i],strURL[i],true);
               		privateTransportFeatures.enableFeature(strURL[i]);
            	//}               
             }   
        }    
        
        //to remove traffic cameras        
        this.removeTrafficCam = function()
        {               
            strURL = new Array();           
            for(var i = 0; i<NumOfKMLFiles; i++)
            {   
                strURL[i] = strTraffCamURL + i + ".kml";  
                privateTransportFeatures.disableFeature(strURL[i]);
                
            }
            removePopup("camera");
        }    

		 //to show pgs signboard
        this.showPGS = function(boolInd)
         {
            if (boolInd == "" || boolInd == null)
            	boolInd = false;
            
             strURL = new Array();                
             for(var i = 0; i<NumOfKMLFiles; i++)
             {   			
 			 	strURL[i] = strPGSURL + i + ".kml"; 
 				// if(!privateTransportFeatures.containsFeatureKey(strURL[i]))
            		//{
                 	privateTransportFeatures.addFeature(strURL[i],strURL[i],true);
                		privateTransportFeatures.enableFeature(strURL[i],boolInd);
             	//}               
              }   
         }    
         
         //to remove pgs signboard        
         this.removePGS = function()
         {               
             strURL = new Array();           
             for(var i = 0; i<NumOfKMLFiles; i++)
             {   
                 strURL[i] = strPGSURL + i + ".kml";  
                 privateTransportFeatures.disableFeature(strURL[i]);
                 
             }
             removePopup("pgs");
         }
         //to show search result for dropdownlist of ERP and traffic cam
       this.showSearchResult = function(panX,panY)
        {    
            //map.moveTo(new OpenLayers.LonLat(panX,panY+0.00005),intBStopZoom);
            //mod by Isaac Yong to add in star marker for search feature.
            objSrcMarker.showOnMap(intBStopZoom,panX,panY+0.00005);
            
        }

		function removePopup(strFilter){
			objMyKMLs.popupIndicator++;
            if(typeof(popup) != "undefined" && popup != null){
            	if(typeof(popup.contentHTML) != "undefined" && popup.contentHTML != null){
	            	if((popup.contentHTML).indexOf("name=\"" + strFilter + "\">") != -1){
						popup.destroy();
			          	popup = null;
		          	}
		    	}
          	}
		}
}
// -- end of for private transport layer-- //

function SearchMarker(){
    //markers' icon setting
    var size = new OpenLayers.Size(18,18);
    var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
    this.icon = new OpenLayers.Icon('http://' + strImgURL + '/landmark.gif',size,offset);
    
    this.showOnMap = function (intZoom,lon,lat){
        if(this.marker != null){
            markers.removeMarker(this.marker);
        }
        this.marker = new OpenLayers.Marker(new OpenLayers.LonLat(lon,lat),this.icon);    

        //objMyKMLs.setTopMostLayer(markers);
        map.moveTo(new OpenLayers.LonLat(lon,lat),intZoom-2);
        map.moveTo(new OpenLayers.LonLat(lon,lat),intZoom);
        markers.addMarker(this.marker);
        //map.zoomTo(0);
        //map.zoomTo(intZoom);
        //objMyKMLs.getLayer(privateTransportlayer).moveTo(map.calculateBounds(),true,false);
    }    
}

//added and modified by Isaac @ 20081215 to encapsulate of function into autoRefresh()
//moved refresh timing into consolidated configuration portion.
function autoRefresh(){

    /* For Mutual Exclusion */
    var flag = "0";
    var NEXT_CMD_ID = 0;
    var t;
    var oneInstance = "NO";
    var intRefreshTimer = (5 * 60 * 1000);//default counter
    var intervalRef;
    /* End of Mutual Exclusion */
    
    this.Start = function (intTimer){
        this.intRefreshTimer = intTimer;
        intervalRef = setInterval("objAutoRefresh.updateFlag(\"1\")", this.intRefreshTimer);
    }
    
    this.ResetCounter = function (){
        intervalRef = window.clearInterval(intervalRef);
        intervalRef = setInterval("objAutoRefresh.updateFlag(\"1\")", this.intRefreshTimer);
    }
    
    this.Refresh = function (boolForce){
    		if (boolForce == null || boolForce == "")
	    		boolForce = false;
    		if(flag == "1" || boolForce)
    		{
    			//parent.basemap.SGTSMap.mergeNewParams({'version': Math.random()});
    			tsrefresh();
    			parent.showframe.news.location.reload(true);
    			parent.document.getElementById('display').innerHTML='Traffic information updated as at <b> ' + Date().toString().substring(0,24) + '</b>';
    			if(parent.showframe.document.checkboxform.cb_PGS.checked){
    			parent.basemap.objprivateTransport.showPGS(true);
    			}
    			if(parent.showframe.document.checkboxform.cb_TI.checked){
					parent.basemap.objprivateTransport.removeTrafficIncidents();
					parent.basemap.objprivateTransport.showTrafficIncidentsForceRefresh();
    				
    			}
    			else {
    				//alert('Refreshed without displaying.');
    			}
    			//alert('Refreshed.');
    			this.updateFlag("0");
    		}
        
        this.ResetCounter();
		}
		
		this.updateFlag = function (temp)
    {
      new Mutex(new UpdateFlagCmd(temp), "go");
    }
		
		/*************************************************************************/
		//private function for autoRefresh
    //To solve concurrency issue for updating countdown flag   
    function Map()
    {
      this.map  = new Object();
       
      // Map API
      this.add     = function(k,o){ this.map[k] = o; }
      this.remove  = function( k ){ delete this.map[k]; }
      this.get     = function( k ){ return k==null ? null : this.map[k]; }
      this.first   = function(   ){ return this.get( this.nextKey( ) ); }
      this.next    = function( k ){ return this.get( this.nextKey(k) ); }
      this.nextKey = function( k ){ for (i in this.map) {
                                       if (!k) return i;
                                       if (k==i) k=null;    /*tricky*/
                                     }
                                     return null;
                                   }
    }
    
    function Mutex( cmdObject, methodName )
    {
      // define static variable and method
      if (!Mutex.Wait) Mutex.Wait = new Map();
      
      Mutex.SLICE = function( cmdID, startID )
      {
        Mutex.Wait.get(cmdID).attempt( Mutex.Wait.get(startID) );
      }
      
      // define instance method
      this.attempt = function( start )
      {
         for (var j=start; j; j=Mutex.Wait.next(j.c.id))
         {
           if (j.enter || (j.number && (j.number < this.number ||
                (j.number == this.number && j.c.id < this.c.id) ) ) )
            return setTimeout("Mutex.SLICE("+this.c.id+","+j.c.id+")",10);
         }
    
         this.c[ this.methodID ]();    //run with exclusive access
         this.number = 0;              //release exclusive access
         Mutex.Wait.remove( this.c.id );
      }
      
      // constructor logic
      this.c        = cmdObject;
      this.methodID = methodName;
      Mutex.Wait.add( this.c.id, this );    //enter and number are
                                               //"false"
      this.enter    = true;
      this.number   = (new Date()).getTime();
      this.enter    = false;
      this.attempt( Mutex.Wait.first() );
    }
    
    function UpdateFlagCmd(temp)
    {
      this.id = ++NEXT_CMD_ID;
      
      this.go = function()
      { 
        flag = temp;
      }
    }
    //End of solving concurrency issue for updating countdown flag
    //end of private function for autoRefresh
    /*************************************************************************/
}

function tsrefresh(){
	var tsvisibility = parent.basemap.SGTSMap.visibility;
	parent.basemap.SGTSMap.destroy();
    parent.basemap.SGTSMap = new OpenLayers.Layer.TileCache("SGRCLMap",[strWMSMapURL],
            "SGRCLMap",{'format':'image/gif','buffer':0,'displayInLayerSwitcher':false,
	    'opacity': 0.5, 'isBaseLayer': false, 'params':{'version': Math.random()}});
    parent.basemap.SGTSMap.setVisibility(tsvisibility);
    map.addLayer(parent.basemap.SGTSMap);
}

