/*
 * MapObject - The JavaScript Mapping Library.
 * http://MapObject.net
 * 
 * Copyright (c) 2006-2007, Mashup Technologies, LLC
 * All rights reserved.
 * http://www.MashupTechnologies.com
 * 
 * The JavaScript code distributed with Google Maps Samples (the "Software") is licensed under the
 * Lesser GNU (LGPL) open source license version 3.
 * 
 * http://www.gnu.org/licenses/lgpl.html
 * 
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 */

/*
 * MapObject - The JavaScript Mapping Library.
 * http://MapObject.net
 * 
 * Copyright (c) 2006-2007, Mashup Technologies, LLC
 * All rights reserved.
 * http://www.MashupTechnologies.com
 * 
 * The JavaScript code distributed with Google Maps Samples (the "Software") is licensed under the
 * Lesser GNU (LGPL) open source license version 3.
 * 
 * http://www.gnu.org/licenses/lgpl.html
 * 
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 * 
 */

/*
* MapBuilder Integrator 2.1.0
* Copyright(c) 2006-2007, Mashup Technologies, LLC.
* http://mashuptechnologies.com
*/


//Class which handles record/property view
Ext.namespace('MapObject.widget');

/**
* MapViewer component designed to TODO...
* @namespace MapObject.app.se32bj
* @class recordViewer
* @constructor
* @param {Ext.data.Store} The instance of data source store object.
*/
MapObject.widget.MapViewer = function(config)
{
	this.init(config);
}

MapObject.widget.MapViewer.prototype = {
}

/* Dev - event model */
Ext.extend(MapObject.widget.MapViewer, Ext.util.Observable, {
	
	/**
	* Map Viewer
	* @private
	* @type {MapObject.widget.MapViewer} 
	*/
	mapViewer: null,

	/**
	* Data store
	* @private
	* @type {Ext.data.Store}
	*/
	ds: null,
	
	/**
	* Grid
	* @private
	* @type {Ext.grid.Grid}
	*/
	grid: null,
	
	/**
	* Record Viewer
	* @private
	* @type {MapObject.app.se32bj.recordViewer}
	*/
	recordViewer: null,

	/**
	* Record Viewer
	* @private
	* @type {MapObject.app.se32bj.tooltipTemplate}
	*/
	tooltipTemplate: null,

	/**
	* Application messages
	* @private
	* @type {Object} A  key-value hash of application messages.
	*/
	messages: {
		headerHelp: 'Click on a grid headers to sort results. Select any record to see detail information.'
	},

	/**
	* Dataset limit.
	* @private
	* @type {Integer} 
	*/
	datasetLimit: 400, 

	/**
	* Set center automatically from a data feed.
	* @public
	* @type {Bool} Set center from data source or not 
	*/
	autoCenter: true, 

	/**
	* True if the control key was down during the click event
	* @public
	* @type {boolean} 
	*/
	ctrlKey: false, 

	/**
	* Initialize object
	* @param none
	* @return none
	*/
    init: function(config){

		// Set properties from config literal
		this.ds = config.ds;
		this.grid = config.grid;
		this.recordViewer = config.recordViewer || null;
		this.tooltipTemplate = config.tooltipTemplate || null;
		// Set map center received from a server
		this.autoCenter = config.autoCenter;
		// Calculate boundaries and set center and zoom level
		this.calculateCenter = config.calculateCenter || false;
		this.focusGridRow = config.focusGridRow;
		this.gridHelp = config.gridHelp || null;
		this.cabinswitch = config.cabinswitch ;
		// Register event to capture keydown/keyup events
		Ext.EventManager.addListener(document, 'keydown', this.keydown.createDelegate(this));
		Ext.EventManager.addListener(document, 'keyup', this.keyup.createDelegate(this));


		/* Store.load via HttpProxy is async process - the result is not available immediately after the stmt executes.
		* We should use onLoad handler
		*/
		this.ds.on('load', this.dsLoad, this);


		/* 
		* beforeload Event - Fires before a request is made for a new data object. 
		* If the beforeload handler returns false the load action will be canceled. 
		* 
		* Main responsibility of this hook is to pass search criteria to the server.
		* searchQuery: fieldRep=Select...&address=&zip=&census=&date1=&date2=&owner=Select...&employer=Select...&focus=Select...&ADF_Gap=&construction=Select...
		*/
		this.ds.on('beforeload', this.dsBeforeLoad, this);

        //
        // Grid
		//

		this.grid.on('rowclick', this.gridRowClick, this);

		this.grid.on('mouseover', this.gridMouseOver, this);

		this.grid.on('mouseout', this.gridMouseOut, this);

        this.grid.render();

		// Instantiate GoogleMap class
		this.mapViewer = new MapObject.proxy.GoogleMap(config.mapConfig.container, (config.mapConfig || {}));

		this.mapViewer.loadMap();

		/* Use overlay instead 
		* // Use MarkerManager
		* this.mapViewer.getMapProxy().markersEngine = 'MarkerManager';
		*/

		//
		// Register map viewers callback functions 
		//

		// Hook to get tooltip text
		this.mapViewer.getMapProxy().getToolTipText = this.getToolTipText.createDelegate(this);

		// Hook to handle tooltips onToolTipMouseOut
		this.mapViewer.getMapProxy().onMarkerMouseOut = this.onMarkerMouseOut.createDelegate(this);

		// Hook to handle tooltips onMarkerMouseOver
		this.mapViewer.getMapProxy().onMarkerMouseOver = this.onMarkerMouseOver.createDelegate(this);

		// Hook to handle onMarkerClick event
		this.mapViewer.getMapProxy().onMarkerClick = this.onMarkerClick.createDelegate(this);

        // Finally load data
        this.ds.load();
    },
     

	//
	// DataStore
	//

	/* 
	* Data store on load callback function
	*/
	dsLoad: function (ds) {
		// Center map
		var mapData = this.ds.reader.jsonData.map;

		// Make sure mape has been loaded before we add any markers
		var map = this.mapViewer.getMapProxy().mapObject;
		if (!map.isLoaded()){
			if (this.autoCenter) {
				this.mapViewer.defaultZoom = parseInt(mapData.zoom);
				this.mapViewer.getMapProxy().setCenter(parseFloat(mapData.lat), parseFloat(mapData.lng), this.mapViewer.defaultZoom); 
			}
			else {
				// run setCenter method
				this.setCenter();
			}
		}
			
		// Build icons
		if (this.ds.reader.jsonData.icons) {
			this.mapViewer.buildIcons(this.ds.reader.jsonData.icons);
		}

		// Hide details
		this.recordViewer && this.recordViewer.hide();

		//Clear map - check if map is actually loaded
		if (this.mapViewer.getMapProxy().mapObject != null) {
			this.mapViewer.getMapProxy().clearOverlays();
		}

		//BBF add other road adds
		//segment1
		var points1 =
							[
		new GLatLng(35.738605,-83.481663),
		new GLatLng(35.739006,-83.481663),
		new GLatLng(35.739128,-83.481964),
		new GLatLng(35.738954,-83.4822),
		new GLatLng(35.738723,-83.481991),
		new GLatLng(35.738523,-83.481873),
		new GLatLng(35.738301,-83.481814),
		new GLatLng(35.737952,-83.481604),
		new GLatLng(35.737682,-83.481588),
		new GLatLng(35.737569,-83.481771),
		new GLatLng(35.737447,-83.482066),
		new GLatLng(35.737256,-83.481964),
		new GLatLng(35.737112,-83.481653),
		new GLatLng(35.737199,-83.481379),
		new GLatLng(35.737312,-83.48117),
		new GLatLng(35.737412,-83.480923),
		new GLatLng(35.737534,-83.480848),
		new GLatLng(35.737987,-83.48103),
		new GLatLng(35.738431,-83.481224),
		new GLatLng(35.738845,-83.481207),
		new GLatLng(35.739145,-83.480907),
		new GLatLng(35.739372,-83.480687),
		new GLatLng(35.739629,-83.480553),
		new GLatLng(35.739829,-83.480424)
		];
		var polyline = new GPolyline(points1,'#FFFFFF',5,1);
		map.addOverlay(polyline);
						
		//Segment 2		
		var points2 =
					[
		new GLatLng(35.73598,-83.48146),
		new GLatLng(35.736785,-83.480945),
		new GLatLng(35.737199,-83.480821),
		new GLatLng(35.7376,-83.480864)


		];
		var polyline = new GPolyline(points2,'#FFFFFF',5,1);
		map.addOverlay(polyline);

		//Segment 3		
		var points3 =
					[
		new GLatLng(35.737976,-83.48098),
		new GLatLng(35.737978,-83.480762),
		new GLatLng(35.738174,-83.480355),
		new GLatLng(35.738514,-83.480263),
		new GLatLng(35.738806,-83.480408),
		new GLatLng(35.739084,-83.480923)





		];
		var polyline = new GPolyline(points3,'#FFFFFF',5,1);
		map.addOverlay(polyline);

		//Segment 4		
		var points4 =
					[
		new GLatLng(35.738235,-83.479384),
		new GLatLng(35.738462,-83.479684),
		new GLatLng(35.738732,-83.479673),
		new GLatLng(35.739058,-83.479893),
		new GLatLng(35.739328,-83.480108),
		new GLatLng(35.739359,-83.480253),
		new GLatLng(35.739219,-83.480365)




		];
		var polyline = new GPolyline(points4,'#FFFFFF',5,1);
		map.addOverlay(polyline);

		//Segment 5		
		var points5 =
					[
		new GLatLng(35.736855,-83.479646),
		new GLatLng(35.737099,-83.479357),
		new GLatLng(35.73736,-83.478938),
		new GLatLng(35.737465,-83.478391),
		new GLatLng(35.737639,-83.477833),
		new GLatLng(35.737835,-83.477737),
		new GLatLng(35.738013,-83.477715),
		new GLatLng(35.738144,-83.477871),
		new GLatLng(35.738196,-83.478069),
		new GLatLng(35.738196,-83.478391),
		new GLatLng(35.738283,-83.478627),
		new GLatLng(35.73824,-83.478992),
		new GLatLng(35.738231,-83.479346),
		new GLatLng(35.738144,-83.479797),
		//new GLatLng(35.738144,-83.479797),
		new GLatLng(35.738083,-83.480406)




		];
		var polyline = new GPolyline(points5,'#FFFFFF',5,1);
		map.addOverlay(polyline);

		//Segment 6		
		var points6 =
					[
		new GLatLng(35.738078,-83.477688),
		new GLatLng(35.738279,-83.477721),
		new GLatLng(35.738453,-83.477844),
		new GLatLng(35.738501,-83.478214),
		new GLatLng(35.738579,-83.478611),
		new GLatLng(35.738758,-83.478836),
		new GLatLng(35.73888,-83.478938),
		new GLatLng(35.739215,-83.478992),
		new GLatLng(35.739467,-83.479303),
		new GLatLng(35.739724,-83.479577),
		new GLatLng(35.739859,-83.479604),
		new GLatLng(35.740007,-83.479604),
		new GLatLng(35.74033,-83.479357),
		new GLatLng(35.740408,-83.479067),
		new GLatLng(35.740356,-83.478681),
		new GLatLng(35.740147,-83.477967),
		new GLatLng(35.740047,-83.477753),
		new GLatLng(35.739868,-83.477651),
		new GLatLng(35.739441,-83.477672),
		new GLatLng(35.739145,-83.477785),
		new GLatLng(35.738971,-83.47808),
		new GLatLng(35.738958,-83.478364),
		new GLatLng(35.739041,-83.47867),
		new GLatLng(35.739276,-83.479078)




		];
		var polyline = new GPolyline(points6,'#FFFFFF',5,1);
		map.addOverlay(polyline);

		//Segment 7		
		var points7 =
					[
		new GLatLng(35.739390,-83.47910),
		//new GLatLng(35.739480,-83.47800),
		new GLatLng(35.739546,-83.478649),
		new GLatLng(35.739655,-83.478515),
		new GLatLng(35.739764,-83.47845	),
		new GLatLng(35.739899,-83.478354)
		//new GLatLng(35.739916,-83.478198)



		];
		var polyline = new GPolyline(points7,'#FFFFFF',5,1);
		map.addOverlay(polyline);

		//Segment 8		
		var points8 =			[
		new GLatLng(35.739894,-83.477683),
		new GLatLng(35.739703,-83.477951),
		new GLatLng(35.739437,-83.478236)



		];
		var polyline = new GPolyline(points8,'#FFFFFF',5,1);
		map.addOverlay(polyline);

						
		
		
		
		
		
		
		function processDetails(record)
		{
			// Add locations to a map
			var id = record.get('id');
			var lat = record.get('lat');
			var lng = record.get('lng');

			// Add marker
			var marker = this.mapViewer.getMapProxy().addMarker(id, lat, lng, this.mapViewer.iconsSet[record.get('icon')]);

			// Calculate boundaries 
			bounds.extend(marker.getLatLng());

			newIDs.push(id);
		}


		var newIDs = [];

		// Calculate boundaries 
		var bounds = new GLatLngBounds();

		// Process data store records
		this.ds.each(processDetails, this);

		/*
		* Code block loop calculates intersection betwenn already loaded markers and new ones 
		* and removes markers which are outside of intersection scope (they are not loaded).
		*/
		/*
		var markers = this.mapViewer.getMapProxy().gmarkers;
		for(var key in markers){
			if(typeof markers[key] != "function"){
				var found = false;
				for (var i=0, len=newIDs.length; i < len; i++) {
					// entry fpund
					if (key == newIDs[i]) {
						found = true;
						break;
					}
				}
				if (!found) {
					// Check if marker has been already added
					this.mapViewer.getMapProxy().removeOverlay(markers[key]);
					//markers.remove(markers[key]);
					markers[key] = null;
				}
			}
		}
		*/

		// Calculate boundaries 
		if (this.calculateCenter && !bounds.isEmpty()) {
			var worklat,worklng;
			var center = bounds.getCenter();
			var zoom = map.getBoundsZoomLevel(bounds);
			//----------True means requesting individual cabin, parm from map.php
			if (this.cabinswitch){
				zoom = zoom - 5;		//Zoom out so customer has Gatlinburg view zoom value = zoom out
				//create another map point center is readonly
//				worklat = center.lat() + parseFloat('.0170');
				worklat = center.lat() - parseFloat('.0170');
				worklng = center.lng();
				center1 = new GLatLng(worklat,worklng);		//bump center lat up so tooltip off of google menu
//				center1.y = parseFloat(center1.y) + parseFloat('.0070'); ???? delete	
				map.setCenter(center1, zoom);
				this.cabinswitch = false ;
							}
				else	{
				map.setCenter(center, zoom);
				};}
				 	
					
		
		else 
		// Set center from a data feed
		if (this.autoCenter) {
			this.mapViewer.defaultZoom = parseInt(mapData.zoom);
			this.mapViewer.getMapProxy().setCenter(parseFloat(mapData.lat), parseFloat(mapData.lng), this.mapViewer.defaultZoom); 
		}
		else {
			// run setCenter method
			this.setCenter();
		} 

		// Run a hook method
		this.postDSLoadHook(ds);
				
		// Save map position
		this.mapViewer.getMapProxy().mapObject.savePosition();

		/* Use overlay instead 
		* //Create new marker manager
		* var mgr = new GMarkerManager(this.mapViewer.getMapProxy().mapObject);
		* mgr.addMarkers(batch, '9');
		* mgr.refresh();
		*/

	},//if (this.calculateCenter && !bounds.isEmpty()) {

	/* 
	* beforeload Event - Fires before a request is made for a new data object. 
	* If the beforeload handler returns false the load action will be canceled. 
	* 
	* Main responsibility of this hook is to pass search criteria to the server.
	* searchQuery: fieldRep=Select...&address=&zip=&census=&date1=&date2=&owner=Select...&employer=Select...&focus=Select...&ADF_Gap=&construction=Select...
	*/
	dsBeforeLoad: function(options) {
		/* Enhanced by overlay removing in the dsLoad method.
		* clearOverlays removes all records which is not good when we are using dynamic 
		* data loading on map zooming/panning
		// Hide details
		this.recordViewer && this.recordViewer.hide();

		//Clear map - check if map is actually loaded
		if (this.mapViewer.getMapProxy().mapObject != null) {
			this.mapViewer.getMapProxy().clearOverlays();
		}
		*/

		//Serialize form and send parameters to a server
		//moved outside mapviewer class 
		//options.baseParams.searchQuery = Ext.Ajax.serializeForm('searchForm');
		return true;
	},

	gridRowClick: function(gridRef, rowIndex, e){ 
		//grid.getView().getRow(this.ds.indexOf(record));
		var selectedRecord = this.grid.getSelectionModel().getSelected();
		// selectedRecord === undefined if user clicked on a grid header/footer
		if (selectedRecord != undefined) {
			//find record id
			var id = selectedRecord.get('id');

			this.recordViewer && this.recordViewer.showDetails(id);

			this.moveIntoMapView(id);

			// Set active marker
			this.mapViewer.getMapProxy().setActiveMarker(this.mapViewer.getMapProxy().getMarker(id));

			// Change to Detail tab if we are on Listing. Otherwise stay on a current tab.
		}
	},

	gridMouseOver: function(e, t){

		var rowIdx;
		var view = this.grid.getView();
		if((rowIdx = view.findRowIndex(t)) !== false){

			//find record id
			var id = this.ds.getAt(rowIdx).get('id');
			//this.setActiveMarkerIcon(row, true);
			this.setActiveMarkerIcon(id, true);

			//var r = view.getRowComposite(row);
			//row is a row index
			/* Move map on record selection only 
			* this.moveIntoMapView(row);
			*/
		}
	},


	gridMouseOut: function(e, t){
		var rowIdx;
		var view = this.grid.getView();
		if((rowIdx = view.findRowIndex(t)) !== false){
			//find record id
			var  id = this.ds.getAt(rowIdx).get('id');
			this.setActiveMarkerIcon(id, false);
			//this.setActiveMarkerIcon(row, false);
		}
	},

	/**
	* Hook method which runs when DS load method finishes its executions.
	* @param {Ext.data.Store} data store
	* @return none
	*/
	postDSLoadHook: function(ds) {
		// Check total rwos count which is returned from a server
		var totalCount = parseInt(ds.reader.jsonData.totalRowsCount);
		if (totalCount == 0){
			this.gridHelp && Ext.get(this.gridHelp).update("0 Cabins found. Please adjust your selection criteria.");
		}
		// Show alert message
		else if (totalCount > this.datasetLimit) {
			this.gridHelp && Ext.get(this.gridHelp).update(totalCount + " record" + ((totalCount == 1) ? "" : "s")+ " found. " + this.datasetLimit + " records displayed. " + this.messages.headerHelp);
			alert ("Please adjust selection criteria to return less than " + this.datasetLimit + " records.");
		} 
		else { 
			this.gridHelp && Ext.get(this.gridHelp).update(totalCount + " record" + ((totalCount == 1) ? "" : "s")+ " found. " + this.messages.headerHelp);
		}
	},

	/**
	* Zoom to marker on a maximum zoom
	* @param {String} Matker id
	* @return none
	*/
	zoomToMax: function(id) {
		if (!id) id = this.mapViewer.getMapProxy().activeMarker.id;
		this.mapViewer.getMapProxy().mapObject.setCenter(this.mapViewer.getMapProxy().getMarker(id).getPoint(), 16);
	},

	/**
	* Reset map to its original state
	* @param none
	* @return none
	*/
	resetMap: function() {
		// Restore map position
		this.mapViewer.getMapProxy().mapObject.returnToSavedPosition();
	},

	/**
	* Center map on record's marker.
	* @param {String} id Record id.
	* @return none
	*/
	moveIntoMapView: function(id) {
		this.mapViewer.getMapProxy().panTo(this.mapViewer.getMapProxy().getMarker(id));
	},

	/**
	* Get a tooltip text for a given record id
	* @param {String} id Record id.
	* @return {String} Tooltip HTML markup.
	*/
	getToolTipText: function(id) {
		return ((this.tooltipTemplate && this.tooltipTemplate.getHTML(id)) || '');
	},

	/**
	* Set active marker for a given row.
	* @param {String} id Record id.
	* @param {Boolean} active Active/Inactive marker.
	* @return none
	*/
	setActiveMarkerIcon: function(id, active) {
		this.mapViewer.getMapProxy().setActiveMarkerIcon(this.mapViewer.getMapProxy().getMarker(id), active);
	},


	/**
	* onMarker click event. It selects grid row and fires rowclick event.
	* @param {mixed} marker Record id.
	* @return none
	*/
	onMarkerClick: function (marker) {
		//Select a matching record on a grid
		var index = this.ds.indexOfId(marker.id);

		// Scroll selected row into view
		if (this.focusGridRow) {
			/*
			* var view = this.grid.getView();
			* view.getRow(index).scrollIntoView();
			*/
			var view = this.grid.view;
			row = view.getRow(index);
			var top = row.offsetTop;
	        view.scroller.dom.scrollTop = parseInt(top);
		}

		// Marker selection support
		// Check if row is already selected
		var alreadySelected = this.mapViewer.getMapProxy().isMarkerIDSelected(marker.id);

		if (alreadySelected) {
			this.grid.getSelectionModel().deselectRow(index);
		}
		else {
			// Pass second argument to keep existing selection
			this.grid.getSelectionModel().selectRow(index, this.ctrlKey);
		}
		// EOF Marker selection support

		// Fire event
		this.grid.fireEvent('rowclick');
	},

	/**
	* onMarker mouse over event. 
	* @param {mixed} marker Record id.
	* @return none
	*/
	onMarkerMouseOver: function (marker) {
		/* Possible functionality
		* //Select a matching record on a grid
		* this.grid.getSelectionModel().selectRow(marker.id);
		* 
		* //Todo
		* Scroll an active grid record into view
		*/
	},


	/**
	* onMarker mouse out event. 
	* @param {mixed} marker Record id.
	* @return none
	*/
	onMarkerMouseOut: function (marker) {
	},

	/**
	* Function to initiate search.
	* @param none
	* @return none
	*/
	search: function() {
		//Remove all Records from the Store and fires the clear event.
		this.ds.removeAll();
		this.ds.load();
	},

	/**
	* Function to return map viewer(proxy) for a given API
	* @param {String} api Requested API.
	* @return {MapObject.widget.AbstractMap}
	* TODO: add business logic - api verification
	*/
	getViewer: function(api) {
		return this.mapViewer;
	},

	/**
	* Function to handle keydown event
	* @param {Ext.EventObject} 
	* @return none
	*/
	keydown: function(e) 
	{
		this.ctrlKey = e.ctrlKey;
	},

	/**
	* Function to handle keyup event
	* @param {Ext.EventObject} 
	* @return none
	*/
	keyup: function(e) 
	{
		this.ctrlKey = false;
	},

	/**
	* Function to set center - should be redefined.
	* @param none
	* @return none
	*/
	setCenter: function() {

	},

    EOF: null
}
);

