/*
* MapBuilder Integrator 2.1.0
* Copyright(c) 2006-2007, Mashup Technologies, LLC.
* http://mashuptechnologies.com
*/

//Register app.se32bj namespace
Ext.namespace('MapObject.app.CM');

/* Storage for the last selected location */
MapObject.widget.MapViewer.prototype.lastLocation = null;
/* 
* Select location and do some highlighting
* @param {mixed} string Marker id.
*/
MapObject.widget.MapViewer.prototype.setSelectedLocation = function (id, zoomIn) {
	if (this.lastLocation != null) {
		this.lastLocation.removeClass('locationSelected');	
	}
	// Hignlight location row
	this.lastLocation = Ext.get('location:' + id);
	this.lastLocation.addClass('locationSelected');

	// Set active marker
	var marker = this.mapViewer.getMapProxy().getMarker(id);
	
	var proxy = this.mapViewer.getMapProxy();
	// Restore icon of previos active marker
	if (proxy.activeMarker) {
		proxy.activeMarker.setImage(proxy.activeMarker.getIcon().image);
		// Fix issue with double selection
		proxy.activeMarker = null;
	}
	proxy.setActiveMarkerIcon(marker, true);
	proxy.setActiveMarker(marker);

	// Zoom in?
	if (zoomIn) {
		this.zoomToMax(id);
	}

	/* Code moved from gridRowClick */
	var id = marker.id; 
	
	/* Do not display record details below a map
	* this.recordViewer.showDetails(id);
	*/

	this.moveIntoMapView(id);
	
}
/**
* onMarker click event. It selects grid row and fires rowclick event.
* @param {mixed} marker Record id.
* @return none
*/
MapObject.widget.MapViewer.prototype.onMarkerClick = function (marker) {

	// Find parent row id
	var parent_id = MapObject.app.CM.util.getParentID(marker.id);
	//Select a matching record on a grid
	var index = this.ds.indexOfId(parent_id);

	// Pass second argument to keep existing selection
	this.grid.getSelectionModel().selectRow(index, this.ctrlKey);

	//Expand parent row
	this.grid.plugins.expandRow(index);

	//Select location on a grid
	this.setSelectedLocation(marker.id, false);

	/* VC update 
	* this.grid.fireEvent('rowclick');
	*/
	/* EOF Code moved from gridRowClick */

	// Scroll selected row into view
	var view = this.grid.getView();
	/* Moved to Ext.grid.RowExpander.expandRow 
	* //view.getRow(index).scrollIntoView();
	*/

	/* Do not highlight and fade active row - suggested by MW, 
	Ext.get(view.getRow(index)).highlight(null, {duration: 5});
	*/

	// Hide tooltip
	this.mapViewer.getMapProxy().getTooltip().style.visibility = "hidden";
	
	// Check for locations nearby
	var latLng = marker.getLatLng();
	var lat = latLng.lat();
	var lng = latLng.lng();

   	var record = this.ds.getById(parent_id);
	var dir_link = 'http://maps.google.com/maps?f=d&hl=en&geocode=&saddr=&daddr=' + encodeURIComponent(record.get('title')) + '@' + encodeURIComponent(record.get('lat')) + ',' + encodeURIComponent(record.get('lng'));
	dir_link = '<a style="margin-left: 1em;" target="directions" href="' + dir_link + '">directions</a>';
	
	// Show an info window popup
	this.mapViewer.getMapProxy().mapObject.openInfoWindowHtml(latLng, '<div id="info-window">' + this.tooltipTemplate.getHTML(marker.id) + 
	'<div class="smallText"><a id="zoomTo" href="javascript: MapObject.app.CM.auth.map.mapViewer.zoomToMax();">zoom to</a>' + dir_link + '</div></div>' );

};


// Not sure if we need this
MapObject.widget.MapViewer.prototype.gridRowClick = function(gridRef, rowIndex, e){

	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');

		// Find parent row id
		var parent_id = MapObject.app.CM.util.getParentID(id);

				
		var marker = this.mapViewer.getMapProxy().getMarker(id);

		// Hide tooltip
		this.mapViewer.getMapProxy().getTooltip().style.visibility = "hidden";
	
		// Check for locations nearby
		var latLng = marker.getLatLng();
		var lat = latLng.lat();
		var lng = latLng.lng();

		var record = this.ds.getById(parent_id);
		var dir_link = 'http://maps.google.com/maps?f=d&hl=en&geocode=&saddr=&daddr=' + encodeURIComponent(record.get('title')) + '@' + encodeURIComponent(record.get('lat')) + ',' + encodeURIComponent(record.get('lng'));
		dir_link = '<a style="margin-left: 1em;" target="directions" href="' + dir_link + '">directions</a>';
	
		// Show an info window popup
		this.mapViewer.getMapProxy().mapObject.openInfoWindowHtml(latLng, '<div id="info-window" style="height:300px;">' + this.tooltipTemplate.getHTML(marker.id) + 
		'<div class="smallText"><a id="zoomTo" href="javascript: MapObject.app.CM.auth.map.mapViewer.zoomToMax();">zoom to</a>' + dir_link + '</div></div>' );
	}

	return false; 
};


/**
* Center map on record's marker.
* @param {String} id Record id.
* @return none
*/
MapObject.widget.MapViewer.prototype.moveIntoMapView = function(id) {
	this.mapViewer.getMapProxy().panTo(this.mapViewer.getMapProxy().getMarker(id));
};


/**
 * recordViewer component designed to fetch and render an information block for the individual datasource record.
 * @namespace MapObject.app.CM
 * @class recordViewer
 * @constructor
 * @param {Ext.data.Store} The instance of data source store object.
 */
 
 
MapObject.app.CM.recordViewer = function(ds)
{
	this.init(ds);
}
MapObject.app.CM.recordViewer.prototype = {

	/**
	* A detail panel HTML element
	* @private
	* @type {HTMLElement}
	*/
	detailPanel: null,

	/**
	* Details template
	* @private
	* @type {Ext.Template}
	*/
	detailsTemplate: null,

	/**
	* Data store
	* @private
	* @type {Ext.data.Store}
	*/
	ds: null,

    // Constructor
    init : function(ds){
    	this.ds = ds;

		// Detail view panels
		this.detailPanel = Ext.get('detailPanel');
      
		this.detailsTemplate = new Ext.Template(
			'<div class="details">' +
			'<table class="General" width="99%" border="0" cellspacing="0" cellpadding="2" style="padding-left:0px;">' +
			'<tr><th colspan="1" style="text-align: left;">' + 
			'{comp_name}' + 
			'<img src="/media/icons/marker_20_active.png" alt="Selected Location"/> ' + 
			'<span class="smallText"><a id="zoomTo" href="javascript: void(null);">zoom to</a></span> ' +
			'</th></tr>' + 
			'{content}' +																		
			'</table></div>'
		);
		this.detailsTemplate.compile();

    },

	/**
	* Show details for the record with specified id.
	* @param {String} record id
	* @return none
	*/
    showDetails: function(id) {

		// Find parent row id
		var parent_id = MapObject.app.CM.util.getParentID(id);

    	// Get record from data storage
    	var record = this.ds.getById(parent_id);
        var content = [];

        // find activeMarker
        var activeLocation = record.data;

		var kom1 = "";
		
		if (activeLocation !== null) {
			if (activeLocation.address) content.push("<tr><td>" + activeLocation.address + "</td></tr>");
		
			if(activeLocation.city && activeLocation.state) kom1 = ", ";
			if (activeLocation.city || activeLocation.state || activeLocation.zip) 
				content.push("<tr><td>" + activeLocation.city + kom1 + activeLocation.state + " " + activeLocation.zip + "</td></tr>");
			content.push("<br/>");

			if (activeLocation.phone) content.push("<tr><td>" + activeLocation.phone + "</td></tr>");
		}
		
		if (record.get('website')) content.push("<tr><td><a href='" + record.get('website') + "'>" + record.get('website') + "</a></td></tr>");

		if (activeLocation !== null) {
			if (activeLocation.ContactEmail && (activeLocation.ContactEmail.length>3)) 
				content.push("<tr><td><a href='mailto:" + activeLocation.ContactEmail + "'>" + activeLocation.ContactEmail + "</a></td></tr>");
			content.push("<br/>");
		}
		
	
		
		 this.detailsTemplate.overwrite(this.detailPanel, {
                       id: id,
                       comp_name: record.get('comp_name'),
                       content: content.join("\n")
               });
		
    	this.detailPanel.show();
    },

	/**
	* Hide details block.
	* @param none
	* @return none
	*/
    hide: function () {
    	this.detailPanel.hide();
    },

	// No more trailing commas issues
	EOF:null
}


/**
 * tooltipTemplate component designed to fetch and render a tooltip block for the individual datasource record.
 * @namespace MapObject.app.CM
 * @class tooltipTemplate
 * @constructor
 * @param {Ext.data.Store} The instance of data source store object.
 */
MapObject.app.CM.tooltipTemplate = function(ds)
{
	this.init(ds);
}
MapObject.app.CM.tooltipTemplate.prototype = {

	/**
	* Data store
	* @private
	* @type {Ext.data.Store}
	*/
	ds: null,

	/**
	* Tooltip template
	* @private
	* @type {Ext.Template}
	*/
	template: null,

    // Constructor
    init : function(ds){

    	this.ds = ds;// take with Ext.data.Store in {}
		this.template = new Ext.Template(
			'<div class="tooltip">' +
			'<div class="tooltip-container">' +
			'{content}' +
			'</div></div>'											
		);
		this.template.compile();

    },

	/**
	* Show a tooltip for a given record id including  nearby locations.
	* @param {String} record id
	* @return none
	*/
    getHTML: function(id) {

		var parent_id = MapObject.app.CM.util.getParentID(id);

    	var record = this.ds.getById(parent_id);

		// Get HTML for a master record
		var html = [];
		html.push(this.getHTMLIndividual(id));


	    return this.template.apply(
         	{										
    		   content: html.join("\n")
			}
		);
    },


	/**
	* Show a tooltip for a given record id
	* @param {String} record id
	* @return none
	*/
    getHTMLIndividual: function(id) {

		var parent_id = MapObject.app.CM.util.getParentID(id);

    	var record = this.ds.getById(parent_id);

    	var activeLocation = record.data;

		var content = [];
		var kom1 = "";
		if (!Ext.isEmpty(record.get('title'))) content.push("<h2>" + record.get('title') + "</h2>");
		if (!Ext.isEmpty(record.get('address'))) content.push("<span>" + record.get('address') + "</span><br/>");
		
		if(activeLocation.city && activeLocation.state) kom1 = ", ";
		if (activeLocation.city || activeLocation.state || activeLocation.zip) 
			content.push("<span>" + activeLocation.city + kom1 + activeLocation.state + " " + activeLocation.zip + "</span>");
		content.push("<br/>");

		if (!Ext.isEmpty(activeLocation.phone)) 
			content.push("<span>" + activeLocation.phone + "</span><br/>");

		// Show entity photo
		if (!Ext.isEmpty(record.get('title'))) {
			var imgName = record.get('title').toLowerCase();
			imgName = imgName.split(' ').join('_');

			content.push('<img width="190px" src="http://gacancer.com/about-gcs/office-locations/graphics/offices/'+ imgName +'.jpg" />');
		}

		content.push('<br/> <span class="instruct">Click the icon for details</span> <br/>');


	    return content.join("\n");
    },

	/**
	* Hide the tooltip block.
	* @param none
	* @return none
	*/
    hide: function () {
    },

	// No more trailing commas issues
	EOF:null
}



MapObject.app.CM.map = function(config) {
	this.init(config);
}

MapObject.app.CM.map.prototype = {

	/**
	* Instance of 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,

	/**
	* Icons
	* @private
	* @type {Array}
	*/
	icons: null,

	/**
	* Record Viewer
	* @private
	* @type {MapObject.app.CM.recordViewer}
	*/
	recordViewer: null,

	/**
	* Record Viewer
	* @private
	* @type {MapObject.app.CM.tooltipTemplate}
	*/
	tooltipTemplate: null,

	/**
	* Max number of waypoints used for directions generation.
	* See http://groups.google.com/group/Google-Maps-API/browse_thread/thread/5a4171dc5ec11551#19bb341d84d8cd9f
	* @private
	* @type {int}
	*/
	directionsMax: 23,

	/**
	* Indicates if data feed has been loaded at least one.
	* @private
	* @type {boolean}
	*/
	dataInitialized: false,

	/**
	* Storage for the "Tips for Best Use" window object
	* @private
	* @type {Ext.Window}
	*/
	tipsWin: null,
	
	/**
	* Initialize object
	* @param none
	* @return none
	*/
    init : function(config){

    	// Copy all config properties to the object
	    Ext.apply(this, config);

		// Set some configuration options
		MapObject.widget.MapViewer.prototype.mapCenter = this.mapCenter	;
		MapObject.widget.MapViewer.prototype.areaConfig = this.areaConfig;
		MapObject.widget.MapViewer.prototype.allowEdit = this.allowEdit;
		MapObject.widget.MapViewer.prototype.webPath = this.webPath;
		MapObject.widget.MapViewer.prototype.setCenter = function() {
			this.mapViewer.getMapProxy().setCenter(parseFloat(this.mapCenter.point.lat), parseFloat(this.mapCenter.point.lng), parseInt(this.mapCenter.zoom));
		}

    	//
    	// Data Store
    	//
    	// Define the Data Store
		this.ds = new Ext.data.Store({
			// load using script tags for cross domain, if the data in on the same domain as
			// this page, an HttpProxy would be better
			//proxy: new Ext.data.ScriptTagProxy({
			// Use XML HTML Request
			proxy: new Ext.data.HttpProxy({
				url: 'api/search.php',
				nocache: true,
				disableCaching: true
			}),
			/* Search Parameters */
	        baseParams: {test:false},

			// create reader that reads the markers
			reader: new Ext.data.JsonReader({
				root: 'entityList',
				id: 'Entity_ID'
			}, [
				// Make sure id is present as a part of record
				{name: 'id', mapping: 'Entity_ID'},
				{name: 'lat', type: 'float', mapping: 'Latitude'},
				{name: 'lng', type: 'float', mapping: 'Longitude'},
				{name: 'title', mapping: 'Title'},
				{name: 'website', mapping: 'website'},
				{name: 'blog', mapping: 'Blog'},
				{name: 'type', mapping: 'EntityType'},
				{name: 'ContactEmail', mapping: 'Email'},
				{name: 'icon', mapping: 'icon'},
				{name: 'address', mapping: 'Address'},
				{name: 'city', mapping: 'City'},
				{name: 'zip', mapping: 'Zip'},
				{name: 'state', mapping: 'State'},
				{name: 'phone', mapping: 'Phone'},
				{name: 'docsNum', mapping: 'docsNum', type: 'int'},
				{name: 'doctorsList', mapping: 'doctorsList'},
				{name: 'markers', mapping: 'markers'},
				{name: 'locNum', mapping: 'locNum', type: 'int'}
			])
		});


		/*
		* 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...
		*/
		function beforeload(options) {
			//Serialize form and send parameters to a server
			options.baseParams.searchQuery = Ext.Ajax.serializeForm('searchForm');

			// Hide BIO panel
			if (MapObject.app.CM.bioViewer.detailPanel) {
				MapObject.app.CM.bioViewer.detailPanel.hide();
			}
			return true;
		}
		this.ds.on('beforeload', beforeload, this);


		this.ds.on('load', function(ds) {
			// Show errors
			if (this.dataInitialized && ds.reader.jsonData.errors && ds.reader.jsonData.errors.length > 0) {
				alert(ds.reader.jsonData.errors.join("\n"));
		    }
		    // Sat dataInitialized flag to true.
		    this.dataInitialized = true;

		}, this);


    	//
    	// Grid
    	//

		// RowSelectionModel
		// extjs2 var sm = new Ext.grid.RowSelectionModel({singleSelect:true});
			    

		// row expander
		var expander = new MapObject.app.CM.RowExpander({
			tpl : new Ext.Template(
	            '{locHTML}',
	            '{profHTML}'
			),
			// Pass additional template to describe locations
			loctpl : new Ext.Template(
				'{Address}'
			),
			// Pass additional template to describe proffesionals
			proftpl : new Ext.Template(
				'{FirstName} {LastName}, {Suffix}. '
			),
			singleExpand: true,
			webPath: config.webPath,
			allowEdit: config.allowEdit
		});

		// the DefaultColumnModel expects this blob to define columns. It can be extended to provide
        // custom or reusable ColumnModels
        var colModel = new Ext.grid.ColumnModel([
        	expander,
			/* We do not use internal 'id' column anymore
			* {id: "id", header: "ID", width: 70, sortable: false, dataIndex: 'id', hidden:true },
			*/
			{id:'name', header: "Office", width: 180, sortable: true, hideable: false, renderer: officeRenderer, dataIndex: 'title'},
			{id:'directions', header: "", width: 70, sortable: false, hideable: false, renderer: directionRenderer, dataIndex: 'title'}
		]);

		// Custom renderer function to render Company, City
		function officeRenderer(v, p, record){
			return v;
		}
		// Custom renderer function to generate a get directions link
		function directionRenderer(v, p, record){
			var link = 'http://maps.google.com/maps?f=d&hl=en&geocode=&saddr=&daddr=' + encodeURIComponent(v) + '@' + encodeURIComponent(record.get('lat')) + ',' + encodeURIComponent(record.get('lng'));
			return '<a target="directions" href="' + link + '">Directions</a>';
		}
		// Custom renderer function to render empty float values like N/A
		function floatRenderer(v, p, record){
			var formatted = Ext.util.Format.usMoney(v); // format: $1,234.00
			//return isNaN(v) ? 'N/A' : ((Ext.isEmpty(v) || (v == 0)) ? 'N/A' : formatted.substr(1, formatted.length - 4));
			return isNaN(v) ? 'N/A' : ((Ext.isEmpty(v) || (v == 0)) ? 'N/A' : v);
		}
		
		// Set custom renderer for a "Customer Name" column
		//colModel.setRenderer(colModel.getIndexById('name'), function (value, p, record) {
		//	return value + ", " + record.data['f_name'];
		//});

        // create the Grid
        this.grid = new Ext.grid.GridPanel({
        	renderTo: 'grid-container',
            store: this.ds,
            cm: colModel,
	        /* title:'Location Listing', */
			width:320,
			height:460,
			viewConfig: {
				forceFit:true
			},
			plugins: expander,
			collapsible: true,
			animCollapse: false,
			loadMask: true,
            /*autoExpandColumn: 'Address' */
			EOF: null
        });

        // Define rowclick event to hide bioPanel content
		this.grid.on('rowclick', 
			function(gridRef, rowIndex, e){ 
			// Detail view panels
			var detailPanel = Ext.get('bioPanel');
			detailPanel.hide();

			var target = e.getTarget();
			// Check if user clicked on a '+' or '-' 
	        if((target.className != 'x-grid3-row-expander') && (target.className != 'x-grid3-td-expander')){
				// Expand row
				this.grid.plugins.toggleToExpandRow(rowIndex);
			}

		}, this);

        /* Do not use record viewer.
        * // Record viewer
        * this.recordViewer = new MapObject.app.CM.recordViewer(this.ds);
        */
        this.recordViewer = null;

        // Record viewer
        this.tooltipTemplate = new MapObject.app.CM.tooltipTemplate(this.ds);

		// Instantiate MapViewer class
		this.mapViewer = new MapObject.widget.MapViewer( {
			'ds': this.ds,
			'grid': this.grid,
			'recordViewer': this.recordViewer,
			'tooltipTemplate': this.tooltipTemplate,
			'gridHelp' : null,
			'autoCenter' : false, 
			'mapConfig' : {
				'container' : 'map-container',
				'mapControls' : {
					// Creates a control with buttons to pan in four directions, and zoom in and zoom out.
					smallMapControl: false,
					// 	Creates a control with buttons to pan in four directions, and zoom in and zoom out, and a zoom slider.
					largeMapControl: true,
					// Creates a control with buttons to zoom in and zoom out.
					smallZoomControl: false,
					// Creates a control that displays the map scale.
					scaleControl: false
				},
				'tooltipEngine' : 'v2',
				'markersEngine' : 'MarkerManager',
				'icons' : this.icons
			}
		});
		this.mapViewer.messages.headerHelp = '<br>Click a column header to sort results or change header criteria.';


		/*
		// Define hook method to display results
		this.mapViewer.postDSLoadHook = function(ds) {

		    //Set rows found

			// Check total rwos count which is returned from a server
			var totalCount = parseInt(ds.reader.jsonData.totalRowsCount);
			var totalProf = parseInt(ds.reader.jsonData.totalRowsProf);
			var totalComp = parseInt(ds.reader.jsonData.totalRowsComp);
			var totalLoc = parseInt(ds.reader.jsonData.totalRowsLoc);
			
			if (totalCount == 0){
				Ext.get('gridHelp').update("0 records found. Please adjust your selection criteria.");
			}
			// Show alert message
			else if (totalCount > this.mapViewer.datasetLimit) {
				Ext.get('gridHelp').update("<b>" + totalComp + " companies" + ((totalCount == 1) ? "" : "s") + ", " + 
				totalLoc + " location" + ((totalCount == 1) ? "" : "s") + " " + 
				" and " + totalProf + " professional" + ((totalCount == 1) ? "" : "s") + " found.</b> " + this.mapViewer.datasetLimit + " records displayed. " + this.messages.headerHelp);
				alert ("Please adjust selection criteria to return less than " + this.mapViewer.datasetLimit + " records.");
			} 
			else { 
				Ext.get('gridHelp').update("<b>" + totalComp + " companies" + ((totalCount == 1) ? "" : "s") + ", " + 
				totalLoc + " location" + ((totalCount == 1) ? "" : "s") + " " + 
				" and " + totalProf + " professional" + ((totalCount == 1) ? "" : "s") + " found.</b> " + this.messages.headerHelp);
			}
		};
		*/

		var geocoder = new MapObject.proxy.GoogleGeocoder();
		// Instantiate geocoding widget
		var geocodingPanel = new MapObject.widget.GeoCodingPanel(
			'geocodeAddressInput',
			'geocodeButton',
		    geocoder,
		    this.mapViewer.getViewer('Google')
		)

		//
		// Register application events for misc. HTML elements
		//

		// Attach event to the 'search' button
		Ext.get('searchButton').on('click', function() {
			this.search();
		}, this.mapViewer);
		Ext.get('searchButtonCity').on('click', function() {
			this.search();
		}, this.mapViewer);

		//try {
			// Add filtering handlers
			Ext.get('mapLegend').on('click', this.filterByLegend, this);

			// Add resetMap handler
			Ext.get('resetMap').on('click', this.mapViewer.resetMap, this.mapViewer);

			/* detailPanel display deprecated by Matt
			// Add zoomToMax event handler registered on detailPanel click
			Ext.get('detailPanel').on('click', function(e) {
				var target = e.getTarget();
				if (target.id == "zoomTo") {
					this.zoomToMax(false);
				}
			},
			this.mapViewer);
			*/

			// Register onlick event for the grid element
			Ext.get('grid-container').on('click', function(e) {
				var target = e.getTarget();
				if (target.className == 'rowZoom') {
					var id = target.id.split(':')[1];
					//alert(id);
					this.setSelectedLocation(id, true);
				}
			},
			this.mapViewer);

			// Register onlick event for the auth elements
			Ext.get('signupLink') && Ext.get('signupLink').on('click', function(e) {
				MapObject.app.CM.auth.showForm("signup");
			});
			Ext.get('loginLink') && Ext.get('loginLink').on('click', function(e) {
				MapObject.app.CM.auth.showForm("login");
			});
		/*
		}
		catch (e) {

		}
		*/

          // Finally load data
          this.dataInitialized = false; // flag to prevent from errors output
          //CALLED IN FRAMEWORK this.ds.load();
    },


	/**
	* Show 'Tips for Best Use' popup
	* @param none
	* @return none
	*/
	showTips: function() {
        // create the window on the first click and reuse on subsequent clicks
        if(!this.tipsWin){
            this.tipsWin = new Ext.Window({
                el:'tipsBestView',
                layout:'fit',
                autoScroll: true,
                width:700,
                height:500,
                closeAction:'hide',
                plain: true,
                modal: true,
                resizable: false,
                
                contentEl: 'tipsPanel',

                buttons: [{
                    text: 'Close',
                    handler: (function(){
                        this.tipsWin.hide();
                    }).createDelegate(this)
                }]
            });
        }
        this.tipsWin.show(this);

	},

	/**
	* Show a feedback form
	* @param none
	* @return none
	*/
	showFeedback: function() {
        // create the window on the first click and reuse on subsequent clicks
        if(!this.feedbackWin){
            this.feedbackWin = new Ext.Window({
                el:'feedback',
                layout:'fit',
                width:700,
                height:450,
                closeAction:'hide',
                plain: true,
                modal: false,
                resizable: false,
                hideMode: 'visibility',
                
                contentEl: 'feedbackPanel',
       
                buttons: [{
                    text:'Submit',
                    handler: (function(){
						var feedbackOpt = Ext.Ajax.serializeForm('feedbackForm');

						//Make ajax call and save export parameters in a session
						Ext.Ajax.request({
							url: 'api/sendFeedback.php',
							success: function (response, options) {
		                        this.feedbackWin.hide();
		                        //Remove feddback text
		                        Ext.get("feedback").dom.value = "";
						        Ext.MessageBox.alert('Feedback Status', 'Your feedback has been sent.');
							},
							failure: function () {alert("Feedback failed. Please try again.")},
							scope: this,
							params: {
								'op': feedbackOpt
							}
						});

                    }).createDelegate(this)

                },{
                    text: 'Close',
                    handler: (function(){
                        this.feedbackWin.hide();
                    }).createDelegate(this)
                }]
            });

        }
        this.feedbackWin.show(this);

	},

	/**
	* "Big" filtering
	* @param none
	* @return none
	*/
	filterLow: function() {
		Ext.get("AUM").dom.value = '1000';

		// Set search operation
		MapObject.util.Form.setSelectedValue("AUM_s", "<");

		//Remove all Records from the Store and fires the clear event.
		this.ds.removeAll();
        // Invoke search
        this.ds.load();
	},
	
		/**
	* "Big" filtering
	* @param none
	* @return none
	*/
	filterMediumLow: function() {
		Ext.get("AUM").dom.value = '3000';

		// Set search operation
		MapObject.util.Form.setSelectedValue("AUM_s", "<");

		//Remove all Records from the Store and fires the clear event.
		this.ds.removeAll();
        // Invoke search
        this.ds.load();
	},
	
		/**
	* "Big" filtering
	* @param none
	* @return none
	*/
	filterMedium: function() {
		Ext.get("AUM").dom.value = '100000';

		// Set search operation
		MapObject.util.Form.setSelectedValue("AUM_s", "<");

		//Remove all Records from the Store and fires the clear event.
		this.ds.removeAll();
        // Invoke search
        this.ds.load();
	},
	
		/**
	* "Big" filtering
	* @param none
	* @return none
	*/
	filterHigh: function() {
		Ext.get("AUM").dom.value = '10000';

		// Set search operation
		MapObject.util.Form.setSelectedValue("AUM_s", ">");

		//Remove all Records from the Store and fires the clear event.
		this.ds.removeAll();
        // Invoke search
        this.ds.load();
	},

	/**
	* Event handler to filter records by map legend
	* @param {Ext.EventObject} e
	* @return none
	*/
	filterByLegend: function(e) {
		var target = e.getTarget();

		if (target.id == "showTips") {
			this.showTips();
		}
		else if ((target.id == "showFeedback")) {
			this.showFeedback();
		}
		
	},


	showBoard: function(id) {
	 	alert(id);
	},

    EOF: null
}



/*
 * Ext JS Library 2.0
 * Copyright(c) 2006-2007, Ext JS, LLC.
 * licensing@extjs.com
 *
 * http://extjs.com/license
 */

Ext.grid.RowExpander = function(config){
    Ext.apply(this, config);

    this.addEvents({
        beforeexpand : true,
        expand: true,
        beforecollapse: true,
        collapse: true
    });

    Ext.grid.RowExpander.superclass.constructor.call(this);

    if(this.tpl){
        if(typeof this.tpl == 'string'){
            this.tpl = new Ext.Template(this.tpl);
        }
        this.tpl.compile();
    }

    this.state = {};
    this.bodyContent = {};
};

Ext.extend(Ext.grid.RowExpander, Ext.util.Observable, {
    header: "",
    width: 20,
    sortable: false,
    fixed:true,
    dataIndex: '',
    id: 'expander',
    lazyRender : true,
    enableCaching: false,
    lastExpandedRow: null,
    singleExpand: false,

    getRowClass : function(record, rowIndex, p, ds){
        p.cols = p.cols-1;
        var content = this.bodyContent[record.id];
        if(!content && !this.lazyRender){
            content = this.getBodyContent(record, rowIndex);
        }
        if(content){
            p.body = content;
        }
        return this.state[record.id] ? 'x-grid3-row-expanded' : 'x-grid3-row-collapsed';
    },

    init : function(grid, opt){
        this.grid = grid;

        var view = grid.getView();
        view.getRowClass = this.getRowClass.createDelegate(this);

        view.enableRowBody = true;

        grid.on('render', function(){
            view.mainBody.on('mousedown', this.onMouseDown, this);
        }, this);

    },

    getBodyContent : function(record, index){
        if(!this.enableCaching){
            return this.tpl.apply(record.data);
        }
        var content = this.bodyContent[record.id];
        if(!content){
            content = this.tpl.apply(record.data);
            this.bodyContent[record.id] = content;
        }
        return content;
    },

    onMouseDown : function(e, t){
        if(t.className == 'x-grid3-row-expander'){
            e.stopEvent();
            var row = e.getTarget('.x-grid3-row');
            this.toggleRow(row);
        }
    },

    renderer : function(v, p, record){
        p.cellAttr = 'rowspan="2"';
        return '<div class="x-grid3-row-expander">&#160;</div>';
    },

    beforeExpand : function(record, body, rowIndex){
        if(this.fireEvent('beforeexpand', this, record, body, rowIndex) !== false){
            if(this.tpl && this.lazyRender){
                body.innerHTML = this.getBodyContent(record, rowIndex);
            }
            return true;
        }else{
            return false;
        }
    },

    toggleRow : function(row){
        if(typeof row == 'number'){
            row = this.grid.view.getRow(row);
        }
        this[Ext.fly(row).hasClass('x-grid3-row-collapsed') ? 'expandRow' : 'collapseRow'](row);
    },

    toggleToExpandRow : function(row){
        if(typeof row == 'number'){
            row = this.grid.view.getRow(row);
        }
        this[Ext.fly(row).hasClass('x-grid3-row-collapsed') ? 'expandRow' : 'expandRow'](row);
    },

    expandRow : function(row){
    	// Should we collapse alredy open row?
    	if (this.singleExpand && this.lastExpandedRow) {
    		this.collapseRow(this.lastExpandedRow);
    	}

        if(typeof row == 'number'){
            row = this.grid.view.getRow(row);
        }
        this.lastExpandedRow = row;

        var record = this.grid.store.getAt(row.rowIndex);
       
        // Record might be unavailable after data reloading
        if (!record ) return;

        var body = Ext.DomQuery.selectNode('tr:nth(2) div.x-grid3-row-body', row);
        if(this.beforeExpand(record, body, row.rowIndex)){
            this.state[record.id] = true;
            Ext.fly(row).replaceClass('x-grid3-row-collapsed', 'x-grid3-row-expanded');
            this.fireEvent('expand', this, record, body, row.rowIndex);

			// My custom logic: Scroll selected row into view
			//This doen't scroll to the top this.grid.view.focusRow(row.rowIndex);
			var view = this.grid.view;
			//
			var top = row.offsetTop;
	        view.scroller.dom.scrollTop = parseInt(top);

	        // Select expanded row
	        this.grid.getSelectionModel().selectRow(row.rowIndex);

			/* Code below moves browser window in FF
			if (Ext.isIE)  
				Ext.get(row).focus();
			else {
				row.scrollIntoView();
				Ext.get(row).focus();
			}
			*/
        }

    },

    collapseRow : function(row){
        if(typeof row == 'number'){
            row = this.grid.view.getRow(row);
        }
        var record = this.grid.store.getAt(row.rowIndex);
        
        // Record might be unavailable after data reloading
        if (!record ) return;

        var body = Ext.fly(row).child('tr:nth(1) div.x-grid3-row-body', true);
        if(this.fireEvent('beforcollapse', this, record, body, row.rowIndex) !== false){
            this.state[record.id] = false;
            Ext.fly(row).replaceClass('x-grid3-row-expanded', 'x-grid3-row-collapsed');
            this.fireEvent('collapse', this, record, body, row.rowIndex);
        }
    }
});



MapObject.app.CM.RowExpander = function(config){
    Ext.apply(this, config);

    this.addEvents({
        beforeexpand : true,
        expand: true,
        beforecollapse: true,
        collapse: true
    });

    Ext.grid.RowExpander.superclass.constructor.call(this);

    if(this.tpl){
        if(typeof this.tpl == 'string'){
            this.tpl = new Ext.Template(this.tpl);
        }
        this.tpl.compile();
    }
    if(this.loctpl){
        if(typeof this.loctpl == 'string'){
            this.loctpl = new Ext.Template(this.loctpl);
        }
        this.loctpl.compile();
    }
    if(this.proftpl){
        if(typeof this.proftpl == 'string'){
            this.proftpl = new Ext.Template(this.proftpl);
        }
        this.proftpl.compile();
    }

    
    this.state = {};
    this.bodyContent = {};
};

Ext.extend(MapObject.app.CM.RowExpander, Ext.grid.RowExpander, {
    getBodyContent : function(record, index){

    	var locHTML = []; 	// Locations info
    	var profHTML = []; 	// Proffesionals info
    	var doctorsList = record.data.doctorsList;

		var addressChain1 = []; //[address line 1], [address line 2]
		var addressLine = []; // addressChain1 / addressChain2
		var phoneEmailLine = []; // [phone] / [email1] / [email2]
		// email1 / email 2
		var emailLine = []

		var locData = record.data;

		// Create address entity
		if(!Ext.isEmpty(locData.address)) addressChain1.push(locData.address);
		if(!Ext.isEmpty(locData.city)) addressChain1.push(locData.city);
		var stateZip = locData.state + ' ' +  locData.zip;
		if(!Ext.isEmpty(stateZip.trim())) addressChain1.push(stateZip);

		if (!Ext.isEmpty(addressChain1.join(','))) addressLine.push(addressChain1.join(', '));

		// Create phone/email entity
		if(!Ext.isEmpty(locData.phone)) phoneEmailLine.push(locData.phone);
		if(!Ext.isEmpty(locData.Email) && (locData.Email.length > 3)) emailLine.push('<a href="mailto:' + locData.Email  + '">' + locData.Email  + '</a>');


		var updateLink = '';
		if (this.allowEdit) {
			// Update link 
			updateLink = '&nbsp;<a target="win_update_' + locData.id + '" title="Update Details" href="' + this.webPath + 'secure/entity-edit.php?entity_id=' + encodeURIComponent(record.get('id')) + '"><img src="' + this.webPath + 'media/icons/fam/application_edit.png" alt="Update Details"/></a>';
		}

		locHTML.push('<div id="location:' + locData.id + '">' + '<a href="javascript: void(null);"><img class="rowZoom" id="rowZoom:' + locData.id + '" src="' + this.webPath + 'media/icons/fam/magnifier.png" alt="Zoom In"/></a>' + addressLine.join(" / ") + " " + phoneEmailLine.join(" / ") + updateLink + '</div>');


		// Create content for Physician
		for (var i = 0, len = doctorsList.length; i < len; i++){
			var url = 'http://gacancer.com/about-gcs/physicians/doctordetail.php?LastName=' + encodeURIComponent(doctorsList[i].LastName);
			profHTML.push(
			'<a style="margin-right: 0.2em;" href="' + url +'"><img class="rowBio" width="40px" src="http://gacancer.com/assets/Images/' + encodeURIComponent(doctorsList[i].Photo) + '" alt="View Bio"/></a>' + this.proftpl.apply(doctorsList[i]) + 
			//' <a title="View Bio" id="prof' + doctorsList[i].DoctorID + '" href="javascript: void(null);" onclick="MapObject.app.CM.bioViewer.showBio(' + doctorsList[i].DoctorID + ')">View Bio</a> ' + 
			' <a title="View Details" id="prof' + doctorsList[i].DoctorID + '" href="' + url +'" >View Details</a>') 
		}
    	
    	record.data.locHTML =  locHTML.join("\n");

    	if (profHTML.length > 0) {
	    	record.data.profHTML =  "<b>Physicians:</b><br/>" + profHTML.join("<br />");
		}
		else {
			record.data.profHTML = "";
		}

		// Do not cache 
		this.enableCaching = false;

        if(!this.enableCaching){
            return this.tpl.apply(record.data);
        }
        var content = this.bodyContent[record.id];
        if(!content){
            content = this.tpl.apply(record.data);
            this.bodyContent[record.id] = content;
        }
        return content;
    }

});


/*
* MapBuilder Integrator 2.1.0
* Copyright(c) 2006-2007, Mashup Technologies, LLC.
* http://mashuptechnologies.com
*/

MapObject.app.CM.bioViewer = {
	detailsTemplate: null,
	
	/**
	* Storage for the "Bio" window object
	* @private
	* @type {Ext.Window}
	*/
	bioWin: null,

	/*
	* Show bio popup for a proffesional with a given id
	*/
	showBio: function(id) {
		// Detail view panels
		this.detailPanel = Ext.get('bioPanel');
		//this.detailPanel.hide();

        // create the window on the first click and reuse on subsequent clicks
        if(!this.bioWin){
            this.bioWin = new Ext.Window({
                el:'bioWin',
                layout:'fit',
                autoScroll: true,
                width:600,
                height:'auto',
                closeAction:'hide',
                plain: true,
                modal: true,
                resizable: false,
                
                contentEl: 'bioPanel',

                buttons: [{
                    text: 'Close',
                    handler: (function(){
                        this.bioWin.hide();
                    }).createDelegate(this)
                }]
            });
        }
        //this.bioWin.hide();

		this.detailsTemplate = new Ext.Template(
			'<div class="details">' +
			'<img src="/assets/Images/{Photo}">'+
			'<h1>{FirstName} {LastName}, {Suffix}</h1>'+
			'<ul>'+
			'<li><strong>Board Certified:</strong> {BoardCertified}</li>'+
			'<li><strong>Medical Degree:</strong> {MedicalDegree}</li>'+
			'<li><strong>Residency:</strong> {Residency}</li>'+
			'<li><strong>Fellowship:</strong> {Fellowship}</li>'+
			'<li><strong>Special Interests:</strong> Targeted therapy in lung cancer</li></ul>'+
			'<p>{DoctorBio}</p>'+
			'</div>'
		);
		this.detailsTemplate.compile();

		//Make ajax call and get bio informatiom
		Ext.Ajax.request({
			url: this.webPath + 'api/getBio.php',
			success: (function(response, options) {
	            o = Ext.util.JSON.decode(response.responseText);

				// Details for lease type
				this.detailsTemplate.overwrite(this.detailPanel, o.data);

				this.bioWin.setTitle(o.data.FirstName + ' ' + o.data.LastName + " Bio");
				this.detailPanel.show();
				// Move focus
				//this.detailPanel.focus();
		        this.bioWin.show(this);
				
			}).createDelegate(this),
			failure: function () {alert("Bio loading failed.")},
			scope: this,
			params: {
				'id': id
			}
		});

	}
}

MapObject.app.CM.auth = {
	signupTemplate: null,
	
	/**
	* Storage for the "Signup" window object
	* @private
	* @type {Ext.Window}
	*/
	signupWin: null,
	/**
	* Storage for the "Login" window object
	* @private
	* @type {Ext.Window}
	*/
	loginWin: null,

	/**
	* Storage for the active window object
	* @private
	* @type {Ext.Window}
	*/
	activeWin: null,
	
	/**
	* Storage for the map object
	* @private
	* @type {MapObject.app.CM.map}
	*/
	map: null,
	
	/*
	* Show bio popup for a proffesional with a given id
	*/
	showForm: function(action) {
		// Clear errors
		var elError = Ext.get(action + 'Error');
		elError.dom.innerHTML = '';
		elError.hide();

		if (action ==  "signup") {
			// Content panels
			this.signupPanel = Ext.get('signupPanel');

			// create the window on the first click and reuse on subsequent clicks
			if(!this.signupWin){
				this.signupWin = new Ext.Window({
					el:'signupWin',
					layout:'fit',
					autoScroll: true,
					width:'auto',
					height:'auto',
					closeAction:'hide',
					plain: true,
					modal: true,
	                resizable: false,
                
					contentEl: 'signupPanel',

					buttons: [
					{
						text:'Submit',
						type: 'submit',
						handler: this.submit.createDelegate(this)
                	},
					{
						text: 'Close',
						handler: (function(){
							this.signupWin.hide();
						}).createDelegate(this)
					}]
				});

				// Focus first element
				this.signupWin.addListener("show", function(){
					// Focus first element
					Ext.get('signup-username').focus();
				}, this, {delay:100});

				// Add 'Submit' event handler
				Ext.get('signupForm').on('keydown', function(e) {
					if (e.getKey() == Ext.EventObject.ENTER) {
						this.submit();
					}
				}, this);

			}
			this.activeWin = this.signupWin; 
		}
		// Login
		else {

			// Content panels
			this.loginPanel = Ext.get('loginPanel');

			// create the window on the first click and reuse on subsequent clicks
			if(!this.loginWin){
				this.loginWin = new Ext.Window({
					el:'loginWin',
					layout:'fit',
					autoScroll: true,
					width:'auto',
					height:'auto',
					closeAction:'hide',
					plain: true,
					modal: true,
	                resizable: false,
                
					contentEl: 'loginPanel',

					buttons: [
					{
						text:'Submit',
						type: 'submit',
						handler: this.submit.createDelegate(this)
                	},
					{
						text: 'Close',
						handler: (function(){
							this.loginWin.hide();
						}).createDelegate(this)
					}]
				});

				this.loginWin.addListener("show", function(){
					// Focus first element
					Ext.get('login-username').focus();
				}, this, {delay:100});


				// Add 'Submit' event handler
				Ext.get('loginForm').on('keydown', function(e) {
					if (e.getKey() == Ext.EventObject.ENTER) {
						this.submit();
					}
				}, this);

			}
			this.activeWin = this.loginWin; 
		}
		this.activeWin.action = action;
		this.activeWin.show();

	},

	submit: function() {
		
		var action = this.activeWin.action;

		var params = {};
		if (action ==  "signup") {
			params = Ext.Ajax.serializeForm('signupForm');
		}
		// login
		else {
			params = Ext.Ajax.serializeForm('loginForm');
		}

		//Make ajax call and get bio informatiom
		Ext.Ajax.request({
			url: 'api/auth.php',
			params: {
				'action': action,
				'params': params
			},
			scope: this,
			success: (function(response, options) {

	            o = Ext.util.JSON.decode(response.responseText);
				
				/*

				// Details for lease type
				this.signupTemplate.overwrite(this.signupPanel, {
					Name: o.Name,
					Title: o.Title,
					Blog: ((o.Blog == '') ? '' : ('<a href="' + o.Blog + '" target="_blank">Blog</a>')),
					Bio: o.Bio
				});
				this.signupWin.setTitle(o.Name + " Bio");
				*/
				
				var elError = Ext.get(options.params.action + 'Error');
				// Check for errors
				if (o.errors.length > 0) {
					elError.dom.innerHTML = o.errors.join("<br/>") ;
					elError.show();
				}
				// Sucesfull
				else {
					elError.hide();

					// Hide register panel - remove it from DOM
					var elRegister = Ext.get('register');
					elRegister.setVisibilityMode(Ext.Element.DISPLAY);

					var elWelcome = Ext.get('welcome');
					elWelcome.setVisibilityMode(Ext.Element.DISPLAY);

					if (options.params.action == 'signup') {
						// Show thank you message
						elRegister.setVisible(true);
						elWelcome.setVisible(false);

						// Show Thank-you window
				        Ext.MessageBox.alert('Submission Thank You', 'Thanks for registering! Please check your email for an account authentication, and click on the embedded link to head back here and get going with the service.  If you encounter any problems, send an email to <a href="mailto:support@punctuative.com">support@punctuative.com</a>.');

					}
					// Sign in
					else {
						Ext.get('userName').dom.innerHTML = o.Name;

						//elWelcome.show();
						elWelcome.setVisible(true);

						//elRegister.hide();
						elRegister.setVisible(false);

						// Reload data
						this.reloadData();

					} // else
					// Hide popup
					this.activeWin.hide();
				}

				/*
				if (options.params.action == "signup") {
					this.signupPanel.show();
					this.signupWin.show(this);
				}
				// Login
				else {
					this.loginPanel.show();
					this.loginWin.show(this);
				}
				*/
				

			}).createDelegate(this),
			failure: function () {
				this.activeWin.hide();
				alert("Authentication processing failed. Please try again.")
			}
		});
	},

	logout: function() {
		
		//Make ajax call to log out
		Ext.Ajax.request({
			url: 'api/logout.php',
			params: {
				'action': 'logout'
			},
			scope: this,
			success: (function(response, options) {

				var elWelcome = Ext.get('welcome');
				elWelcome.setVisibilityMode(Ext.Element.DISPLAY);
				//elWelcome.hide();
				elWelcome.setVisible(false);

				// Show register panel - remove it from DOM
				var elRegister = Ext.get('register');
				if (elRegister) {
					elRegister.setVisibilityMode(Ext.Element.DISPLAY);
					//elRegister.show();
					elRegister.setVisible(true);
				}

				// Reload data
				this.reloadData();

			}).createDelegate(this),
			failure: function () {
				this.activeWin.hide();
				alert("Log out processing failed. Please try again.")
			}
		});
	},

	reloadData: function() {
		if (this.map === null) return;

		//Remove all Records from the Store and fires the clear event.
		this.map.ds.removeAll();
        // Invoke search
        this.map.ds.load();
	}


}


// Static utilities
MapObject.app.CM.util = {
	/* Get parent id from child record id ("12_334").
	*/
	getParentID: function(id) {
		return id;
		//return id.split("_")[0];
	}

}

/*
* Map geocoder.
*/
MapObject.app.CM.mapGeocoder = {
	init: function(config) {

		// Instantiate GoogleMap class
		this.mapViewer = new MapObject.proxy.GoogleMap(config.container, (config.mapConfig || {}));

		this.mapViewer.multipleDragableMarkers = false;

		this.mapViewer.on('afterloadmap', function () {
			this.mapViewer.setCenter(config.mapCenter.lat, config.mapCenter.lng, config.mapCenter.zoom);
		}, this);

		// Set lat/lng values on a form
		this.setLatLong = function(lat, lon, accuracy) {
			Ext.get('latitude').dom.value = lat;
			Ext.get('longitude').dom.value = lon;
		};
		this.onGeocode = function(lat, lon, accuracy) {
			this.setLatLong(lat, lon, accuracy);

			this.mapViewer.setCenter(lat, lon, this.geocoder.accuracy[0].levels[accuracy]);

			// Add dragable marker 
			this.mapViewer.addDragableOverlay(lat, lon);
		};
			

		this.mapViewer.onMapClick = this.setLatLong;

		// Load map, e.g. set center
		this.mapViewer.loadMap();

		//Add dragable support
		this.mapViewer.registerMapClick();

		this.geocoder = new MapObject.proxy.GoogleGeocoder();

		this.geocoder.on("aftergeocoding", this.onGeocode, this);

		// Add event listener for geocode button
		Ext.get('GeocodeButton').on('click', function () {
			addr = [
				Ext.get('address').dom.value,
				Ext.get('city').dom.value,
				Ext.get('zip').dom.value,
				', GA'
			]
			this.geocoder.geocode(addr.join(" "));
		}, this);

		// Add DragableOverlay if necessary
		if (config.marker && config.marker.lat && config.marker.lng)
		{
			this.mapViewer.addDragableOverlay(config.marker.lat, config.marker.lng);
		}
	}
	
}
