/*
* MapBuilder Integrator 2.1.0
* Copyright(c) 2006-2008, Mashup Technologies, LLC.
* http://mashuptechnologies.com
*/


//Register app.se32bj namespace
Ext.namespace('MapObject.app.CM');

/**
* 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) {

		//Select a matching record on a grid
		var index = this.ds.indexOfId(marker.id);
		// Pass second argument to keep existing selection
		this.grid.getSelectionModel().selectRow(index, this.ctrlKey);
		this.grid.fireEvent('rowclick');

		// Scroll selected row into view
		if (this.focusGridRow) {
			var view = this.grid.getView();
			view.getRow(index).scrollIntoView();
		}

		// Find active record
		record = this.ds.getById(marker.id);
		/* Showing pop up window has been replaced with redirect to a detail page.
		*/
		//Open details in a new window
		var detailsURL = this.webPath + 'event-details.php?id=' + record.get('sid');
		//window.location = detailsURL;
		var newwindow=window.open(detailsURL);
		if (newwindow.focus) {
			newwindow.focus()
		}

		/* SEE COMMENTS ABOVE
		// show InfoWindow
		// build addrees
		var content = [];
		if (!Ext.isEmpty(record.get('address'))) content.push( record.get('address'));
		if (!Ext.isEmpty(record.get('city'))) content.push( record.get('city'));
		if (!Ext.isEmpty(record.get('country'))) content.push( record.get('country'));

		var name = record.get('name');
		var description = record.get('title');
		var calc_date = record.get('calc_date');
		var link = '<br/><a target="_blank" href="/event/' + record.get('sid') + '" title="View Details">View Details</a>' ;
		var updatelink = '';
		var html = '<div class="info-window"><h2>' + name + '</h2> ' + calc_date +' <br/>' + content.join(", ") + '<div class="info-window-container">' + description +  '</div>' +
			link + updatelink + '</div>';
        this.mapViewer.getMapProxy().mapObject.openInfoWindowHtml(marker.getLatLng(), html);
        */
};

/**
 * tooltipTemplate component designed to fetch and render a tooltip block for the individual datasource record.
 * @namespace MapObject.app.vc
 * @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>' +
			'<h2>{time} - {type}</h2>' +
			'<div class="tooltip-container">' +
			'{address}<br/>' +
			'{description}<br/>' +
			'</div></div>'											
		);

		this.template.compile();

    },

	/**
	* Show a tooltip for a given record id
	* @param {String} record id
	* @return none
	*/
    getHTML: function(id) {

    	var record = this.ds.getById(id);
    	var description = record.get('title');

		// build addrees
		var addressLines = [];
		if (!Ext.isEmpty(record.get('address'))) addressLines.push( record.get('address'));
		if (!Ext.isEmpty(record.get('city'))) addressLines.push( record.get('city'));
		if (!Ext.isEmpty(record.get('state'))) addressLines.push( record.get('state'));

        return this.template.apply(
        	{
				type: record.get('name'), 
				address: addressLines.join(", "), 
				time: record.get('calc_date'),
				description: ((description.length > 255) ? (Ext.util.Format.ellipsis(description, 255) + " <b>(click to read more)</b>") : description)
			}                                                                                          
		);
    },

	/**
	* Hide the tooltip block.
	* @param none
	* @return none
	*/
    hide: function () {
    	this.template.hide();
    },

	// No more trailing commas issues
	EOF:null
}


MapObject.app.CM.map = function(opt) {
	this.init(opt);
}

MapObject.app.CM.map.prototype = {
	
	/**
	* City/area name
	* @private
	* @type {string} 
	*/
	area_id: null,

	/**
	* Area configuration options.
	* @private
	* @type {string} 
	*/
	areaConfig: null,

	/**
	* Instance of Gmap2
	* @private
	* @type {Gmap2} 
	*/
	map: null,

	/**
	* Data store
	* @private
	* @type {Ext.data.Store}
	*/
	ds: null,
	
	/**
	* Grid
	* @private
	* @type {Ext.grid.Grid}
	*/
	grid: null,
	
	/**
	* Record Viewer
	* @private
	* @type {MapObject.app.CM.recordViewer}
	*/
	recordViewer: null,

	/**
	* Record Viewer
	* @private
	* @type {MapObject.app.CM.tooltipTemplate}
	*/
	tooltipTemplate: null,

	/**
	* Icons
	* @private
	* @type {Array}
	*/
	icons: null,

	/**
	* Storage for center marker displayed after geocoding.
	* @private
	* @type {GPoint}
	*/
	centerMarker: null,

	/**
	* Initialize object
	* @param none
	* @return none
	*/
    init : function(opt){

    	// Get config option 
    	this.icons = opt.icons;
    	this.area_id = opt.area_id;
    	this.areaConfig = opt.areaConfig;
    	this.allowEdit = opt.allowEdit;
		this.mapCenter = opt.mapCenter;
		this.webPath = opt.webPath; // Installation web path within document root

    	// App init

		/*
		var dt = new Date();
		// Add date widgets
		var cdate = new Ext.form.DateField({
			applyTo: 'cdate',
			allowBlank:true
		});
		//cdate.applyTo('cdate');
		if (cdate.getValue() == "") {
			cdate.setValue(dt.add(Date.DAY, -14));
		}

		var cdate1 = new Ext.form.DateField({
			applyTo: 'cdate1',
			allowBlank:true
		});
		//cdate1.applyTo('cdate1');
		if (cdate1.getValue() == "") {
			cdate1.setValue(dt);
		}
		*/


        //
		// Init map
		//
		/*
		this.map = new GMap2(document.getElementById("map"));
		this.map.addControl(new GSmallMapControl());
		this.map.addControl(new GMapTypeControl());
		// Set map center
		this.map.setCenter(new GLatLng(this.areaConfig.mapCenter.point.lat,this.areaConfig.mapCenter.point.lng), this.areaConfig.mapCenter.zoom);
		*/

		// 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: this.webPath + 'api/search.php',
				nocache: true
			}),
			/* Search Parameters */
	        baseParams: {area_id:this.area_id},

			// create reader that reads the markers
			reader: new Ext.data.JsonReader({
				root: 'eventsList',
				/* totalProperty: 'totalCount', */
				id: 'Event_ID'
			}, [
				// Make sure id is present as a part of record
				/* Sample record:
				* {"cdid":"336","cdate":"2007-09-10","calc_time":"07:30 PM","clatitude":"39.286679","clongitude":"-76.591440",
				* "description":"","address":"400 S. Ann St","name":"Theft","cicon":"theft.png"}
				*/
				{name: 'id', mapping: 'Event_ID'},
				{name: 'type_id', mapping: 'EventType_ID'},
				{name: 'sid', mapping: 'sid'}, // id-hash
				{name: 'lat', mapping: 'Latitude', type: 'float'},
				{name: 'lng', mapping: 'Longitude', type: 'float'},
				{name: 'description', mapping: 'Description'},
				{name: 'title', mapping: 'Title'},
				{name: 'address', mapping: 'Address'},
				{name: 'country', mapping: 'Country'},
				{name: 'state', mapping: 'State'},
				{name: 'city', mapping: 'City'},
				{name: 'name', mapping: 'TypeName'},
				{name: 'icon', mapping: 'icon'},
				{name: 'calc_date', mapping: 'CalcDate'},
				{name: 'calc_time', mapping: 'calc_time'}
				//{name: 'price', type: 'float', mapping: 'Property.Price'},
			])
		});


		/* 
		* 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');
			return true;
		}
		this.ds.on('beforeload', beforeload, this);

		this.ds.on('load', function(ds) {
			// Gat raw JSON data for further custom processing - errors validations
			var rawdata = ds.reader.jsonData;
			if (rawdata.errors.length > 0) {
				Ext.MessageBox.alert("Errors", rawdata.errors.join("<br/>"));
			}

			document.getElementById("recordsCount").innerHTML = "Records found: " + ds.getCount();
			// 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);


		function createMarker(point, name, address, type_id) {
			if (this.icons[type_id]) {
				var marker = new GMarker(point, this.icons[type_id]);
			}
			else {
				var marker = new GMarker(point);
			}
			var html = "<b>" + name + "</b> <br/>" + address;
			GEvent.addListener(marker, 'click', function() {
				marker.openInfoWindowHtml(html);
			});
			return marker;
		}

    	//
    	// Grid
    	//

		// RowSelectionModel
		var sm = new Ext.grid.RowSelectionModel({singleSelect:true});

		// the DefaultColumnModel expects this blob to define columns. It can be extended to provide
        // custom or reusable ColumnModels
        var colModel = new Ext.grid.ColumnModel([
			{header: "", width: (this.allowEdit ? 50 : 30), sortable: false, dataIndex: 'id', renderer: actionColumnRenderer.createDelegate(this)},
			{header: "Event Type", width: 105, sortable: true, dataIndex: 'name'},
			{header: "Date", width: 70, sortable: true, dataIndex: 'calc_date'},
			{header: "Country", width: 50, sortable: true, dataIndex: 'country'},
			{header: "State", width: 40, sortable: true, dataIndex: 'state'},
			{header: "City", width: 140, sortable: true, dataIndex: 'city'},
			{header: "Description", width: 509, sortable: true, dataIndex: 'title'}
		]);

		// Custom renderer function to render 'view details' and 'update' links
		function actionColumnRenderer(v, p, record){
			var links = []				
			// View details 
			links.push('<a target="_blank" title="View Details" href="' + this.webPath + 'event-details.php?id=' + record.get('sid') + '"><img src="' + this.webPath + 'media/icons/fam/application_go.png" alt="View Details"/></a>');
			if (this.allowEdit) {
				// Update link 
				links.push('<a target="_blank" title="Update Details" href="' + this.webPath + 'secure/event-edit.php?event_id=' + encodeURIComponent(record.get('id')) + '"><img src="' + this.webPath + 'media/icons/fam/application_edit.png" alt="Update Details"/></a>');
			}

			return links.join("&nbsp;");
		}

        // create the Grid
        this.grid = new Ext.grid.GridPanel({
        	renderTo: 'grid-container',
            store: this.ds,
            cm: colModel,
	        sm: sm,
			loadMask: false,
			width:944,
			/* height:400, */
			autoHeight: true, 
            //autoExpandColumn: 'description',
			viewConfig: {
				forceFit:false
			},
			collapsible: true,
	        animCollapse: false,
			EOF: null
        });


        // Record viewer
        //this.recordViewer = new MapObject.app.CM.recordViewer(this.ds);

        // 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, 
			'focusGridRow' : false,
			'mapConfig' : {
				'container' : 'map-container',
				'tooltipEngine' : 'v2',
				'mapControls' : {largeMapControl: true},
				'markersEngine' : 'MarkerManager',
				'icons' : this.icons
			}
		});


        //ab this.grid.render();
		

		var geocoder = new MapObject.proxy.GoogleGeocoder();
		// Instantiate geocoding widget
		var geocodingPanel = new MapObject.widget.GeoCodingPanel(
			'geocodeAddressInput',
			'geocodeButton',
		    geocoder,
		    this.mapViewer.getViewer('Google'),
			{showCenterIcon: true}
		)

		//
		// Register application events for misc. HTML elements
		//

		// Attach event to the 'search' button
		var showBtn = Ext.get('search-button');

		// Attach event to the 'search' button
		showBtn.on('click', this.evtSearch, this);

		// Add filtering handlers
		//Ext.get('mapLegend').on('click', this.filterByLegend, this);
		
        // Finally load data
        this.dataInitialized = false; // flag to prevent from errors output
        //this.ds.load();
    },
     
	/**
	* search
	* @param e Event handler
	* @return none
	*/
	evtSearch: function(e) {
		//Remove all Records from the Store and fires the clear event.
		this.ds.removeAll();
        // Invoke search
        this.ds.load();

	}

}

/* 
* Object literal to manage application popup windows.
*/
MapObject.app.CM.popupManager = {

	/**
	* Storage for the "Tips" window object
	* @private
	* @type {Ext.Window}
	*/
	tipsWin: null,
	/**
	* Storage for the "feedback" window object
	* @private
	* @type {Ext.Window}
	*/
	showFeedback: null,

	/**
	* Init popups - add event listeners
	* @param none
	* @return none
	*/
	init: function() {
		// Add filtering handlers
		if (Ext.get('inlineList')) {
			Ext.get('inlineList').on('click', this.showPopup, this);
		}

		if (Ext.get('crime-classifications')) {
			Ext.get('crime-classifications').on('click', this.showPopup, this);
		}
	},

	/**
	* Event handler to show popups.
	* @param {Ext.EventObject} e
	* @return none
	*/
	showPopup: function(e) {
		var target = e.getTarget();

		if ((target.id == "showTips") || (target.id == "crime-classifications")) {
			this.showTips();
		}
		else if ((target.id == "showFeedback")) {
			this.showFeedback();
		}
		
	},
	/**
	* 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: false,
                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: true,
                resizable: false,
                
                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);

	}

}



/*
 * 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 = {};
};


/*
* MapBuilder Integrator 2.1.0
* Copyright(c) 2006-2007, Mashup Technologies, LLC.
* http://mashuptechnologies.com
*/
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,

	/**
	* Signup required fields
	* @private
	* @type array
	*/
	signupRequiredFields: [{el:'signup-email'}, {el:'signup-password'}, {el:'signup-confpassword'}, 
		{el:'crime-alert-address'}, {el:'crime-alert-city'}],
	/**
	* Login required fields
	* @private
	* @type array
	*/
	loginRequiredFields: [{el:'login-username'}, {el:'login-password'}],

	/**
	* Init popups - add event listeners
	* @param none
	* @return none
	*/
	init: function() {

		// 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");
		});
	},
	
	/*
	* 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){
				//Setup some client-side validators
				this.signupRequiredFields = this.setRequiredFields(this.signupRequiredFields);

				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-email').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){
				//Setup some client-side validators
				this.loginRequiredFields = this.setRequiredFields(this.loginRequiredFields);

				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") {
			var valid = this.validateRequiredFields(this.signupRequiredFields);
			if (valid){
				params = Ext.Ajax.serializeForm('signupForm');
			}
			else {
		        //Ext.MessageBox.alert('Signup Error', 'Please enter all required data.');
				// Show a dialog using config options:
				Ext.Msg.show({
					title:'Signup Error',
					msg: 'Please fill-in all required fields.',
					buttons: Ext.Msg.OK,
					icon: Ext.MessageBox.ERROR
				});
			}
		}
		// login
		else {
			var valid = this.validateRequiredFields(this.loginRequiredFields);
			if (valid){
				params = Ext.Ajax.serializeForm('loginForm');
			}
			else {
				// Show a dialog using config options:
				Ext.Msg.show({
					title:'Login Error',
					msg: 'Please fill-in all required fields.',
					buttons: Ext.Msg.OK,
					icon: Ext.MessageBox.ERROR
				});
			}
		}

		if (!valid){
			return;
		}
		//Make ajax call to process authentication request
		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('Thank You', 'Thanks for registering! Please check your email for an account verification info, and click on the embedded link to confirm your email address. If you encounter any problems, email us at <a href="mailto:support@reportsee.com">support@reportsee.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') {
						// Remove entered passwords
						Ext.get('signup-password').dom.value = '';
						Ext.get('signup-confpassword').dom.value = '';
					}
					else {
						// Remove entered password
						Ext.get('login-password').dom.value = '';

					}
				}

				/*
				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() {
		return; // Do  not reload data.

		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();
	},

	setRequiredFields: function(data) {
		for(var i=0, len=data.length; i<len; i++) {
			data[i].obj = new Ext.form.TextField({
				allowBlank: false,
				applyTo: data[i].el,
				selectOnFocus:true
			});
		}
		return data;
	},
	validateRequiredFields: function(data) {
		var valid = true;
		for(var i=0, len=data.length; i<len; i++) {
			valid = valid && data[i].obj.validate();
		}
		return valid;
	}


}
/* Application Tooltip manager */
MapObject.app.CM.toolTipManager = {

	init: function(elements) {
		for (var i=0, len = elements.length; i<len; i++) {
			new Ext.ToolTip({
				target: elements[i].id,
				title: elements[i].title,
				width:350,
				html: elements[i].html,
				trackMouse:true
			});
		}

		Ext.QuickTips.init();
	}
}


/*
* 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 () {
			var stateEl = Ext.get('state').dom;
			var state = stateEl.options[stateEl.selectedIndex].text;
			var countryEl = Ext.get('country').dom;
			var country = countryEl.options[countryEl.selectedIndex].text;

			addr = [];
			if (!Ext.isEmpty(Ext.get('address').dom.value)) {
				addr.push(Ext.get('address').dom.value);
			}
			if (!Ext.isEmpty(Ext.get('city').dom.value)) {
				addr.push(Ext.get('city').dom.value);
			}
			if (!Ext.isEmpty(state) && (stateEl.selectedIndex != 0)) {
				addr.push(state);
			}
			if (!Ext.isEmpty(Ext.get('zip').dom.value)) {
				addr.push(Ext.get('zip').dom.value);
			}
			if (!Ext.isEmpty(country) && (countryEl.selectedIndex != 0)) {
				addr.push(country);
			}

			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);
		}
	}
	
}

/**
 * Ext.ux.form.DateTime Extension Class for Ext 2.x Library
 *
 * @author    Ing. Jozef Sakalos
 * @copyright (c) 2008, Ing. Jozef Sakalos
 * @version $Id: Ext.ux.form.DateTime.js 264 2008-05-16 22:05:36Z jozo $
 *
 * @license Ext.ux.form.DateTime is licensed under the terms of
 * the Open Source LGPL 3.0 license.  Commercial use is permitted to the extent
 * that the code/component(s) do NOT become part of another Open Source or Commercially
 * licensed development library or toolkit without explicit permission.
 * 
 * License details: http://www.gnu.org/licenses/lgpl.html
 */

/*global Ext */

Ext.ns('Ext.ux.form');

/**
 * @class Ext.ux.form.DateTime
 * @extends Ext.form.Field
 */
Ext.ux.form.DateTime = Ext.extend(Ext.form.Field, {
    /**
     * @cfg {String/Object} defaultAutoCreate DomHelper element spec
     * Let superclass to create hidden field instead of textbox. Hidden will be submittend to server
     */
     defaultAutoCreate:{tag:'input', type:'hidden'}
    /**
     * @cfg {Number} timeWidth Width of time field in pixels (defaults to 100)
     */
    ,timeWidth:100
    /**
     * @cfg {String} dtSeparator Date - Time separator. Used to split date and time (defaults to ' ' (space))
     */
    ,dtSeparator:' '
    /**
     * @cfg {String} hiddenFormat Format of datetime used to store value in hidden field
     * and submitted to server (defaults to 'Y-m-d H:i:s' that is mysql format)
     */
    ,hiddenFormat:'Y-m-d H:i:s'
    /**
     * @cfg {Boolean} otherToNow Set other field to now() if not explicly filled in (defaults to true)
     */
    ,otherToNow:true
    /**
     * @cfg {Boolean} emptyToNow Set field value to now if on attempt to set empty value.
     * If it is true then setValue() sets value of field to current date and time (defaults to false)
     */
    /**
     * @cfg {String} timePosition Where the time field should be rendered. 'right' is suitable for forms
     * and 'below' is suitable if the field is used as the grid editor (defaults to 'right')
     */
    ,timePosition:'right' // valid values:'below', 'right'
    /**
     * @cfg {String} dateFormat Format of DateField. Can be localized. (defaults to 'm/y/d')
     */
    ,dateFormat:'m/d/y'
    /**
     * @cfg {String} timeFormat Format of TimeField. Can be localized. (defaults to 'g:i A')
     */
    ,timeFormat:'g:i A'
    /**
     * @cfg {Object} dateConfig Config for DateField constructor.
     */
    /**
     * @cfg {Object} timeConfig Config for TimeField constructor.
     */

    // {{{
    /**
     * private
     * creates DateField and TimeField and installs the necessary event handlers
     */
    ,initComponent:function() {
        // call parent initComponent
        Ext.ux.form.DateTime.superclass.initComponent.call(this);

        // create DateField
        var dateConfig = Ext.apply({}, {
             id:this.id + '-date'
            ,format:this.dateFormat || Ext.form.DateField.prototype.format
            ,width:this.timeWidth
            ,selectOnFocus:this.selectOnFocus
            ,listeners:{
                  blur:{scope:this, fn:this.onBlur}
                 ,focus:{scope:this, fn:this.onFocus}
            }
        }, this.dateConfig);
        this.df = new Ext.form.DateField(dateConfig);
        delete(this.dateFormat);

        // create TimeField
        var timeConfig = Ext.apply({}, {
             id:this.id + '-time'
            ,format:this.timeFormat || Ext.form.TimeField.prototype.format
            ,width:this.timeWidth
            ,selectOnFocus:this.selectOnFocus
            ,listeners:{
                  blur:{scope:this, fn:this.onBlur}
                 ,focus:{scope:this, fn:this.onFocus}
            }
        }, this.timeConfig);
        this.tf = new Ext.form.TimeField(timeConfig);
        delete(this.timeFormat);

        // relay events
        this.relayEvents(this.df, ['focus', 'specialkey', 'invalid', 'valid']);
        this.relayEvents(this.tf, ['focus', 'specialkey', 'invalid', 'valid']);

    } // eo function initComponent
    // }}}
    // {{{
    /**
     * private
     * Renders underlying DateField and TimeField and provides a workaround for side error icon bug
     */
    ,onRender:function(ct, position) {
        // don't run more than once
        if(this.isRendered) {
            return;
        }

        // render underlying hidden field
        Ext.ux.form.DateTime.superclass.onRender.call(this, ct, position);

        // render DateField and TimeField
        // create bounding table
        var t;
        if('below' === this.timePosition || 'bellow' === this.timePosition) {
            t = Ext.DomHelper.append(ct, {tag:'table',style:'border-collapse:collapse',children:[
                 {tag:'tr',children:[{tag:'td', style:'padding-bottom:1px', cls:'ux-datetime-date'}]}
                ,{tag:'tr',children:[{tag:'td', cls:'ux-datetime-time'}]}
            ]}, true);
        }
        else {
            t = Ext.DomHelper.append(ct, {tag:'table',style:'border-collapse:collapse',children:[
                {tag:'tr',children:[
                    {tag:'td',style:'padding-right:4px', cls:'ux-datetime-date'},{tag:'td', cls:'ux-datetime-time'}
                ]}
            ]}, true);
        }

        this.tableEl = t;
        this.wrap = t.wrap({cls:'x-form-field-wrap'});
        this.wrap.on("mousedown", this.onMouseDown, this, {delay:10});

        // render DateField & TimeField
        this.df.render(t.child('td.ux-datetime-date'));
        this.tf.render(t.child('td.ux-datetime-time'));

        // workaround for IE trigger misalignment bug
        if(Ext.isIE && Ext.isStrict) {
            t.select('input').applyStyles({top:0});
        }

        this.on('specialkey', this.onSpecialKey, this);
        this.df.el.swallowEvent(['keydown', 'keypress']);
        this.tf.el.swallowEvent(['keydown', 'keypress']);

        // create icon for side invalid errorIcon
        if('side' === this.msgTarget) {
            var elp = this.el.findParent('.x-form-element', 10, true);
            this.errorIcon = elp.createChild({cls:'x-form-invalid-icon'});

            this.df.errorIcon = this.errorIcon;
            this.tf.errorIcon = this.errorIcon;
        }

        // setup name for submit
        this.el.dom.name = this.hiddenName || this.name || this.id;

        // we're rendered flag
        this.isRendered = true;

        // update hidden field
        this.updateHidden();

    } // eo function onRender
    // }}}
    // {{{
    /**
     * private
     */
    ,adjustSize:Ext.BoxComponent.prototype.adjustSize
    // }}}
    // {{{
    /**
     * private
     */
    ,alignErrorIcon:function() {
        this.errorIcon.alignTo(this.tableEl, 'tl-tr', [2, 0]);
    }
    // }}}
    // {{{
    /**
     * private initializes internal dateValue
     */
    ,initDateValue:function() {
        this.dateValue = this.otherToNow ? new Date() : new Date(1970, 0, 1, 0, 0, 0);
    }
    // }}}
    // {{{
    /**
     * Calls clearInvalid on the DateField and TimeField
     */
    ,clearInvalid:function(){
        this.df.clearInvalid();
        this.tf.clearInvalid();
    } // eo function clearInvalid
    // }}}
    // {{{
    /**
     * Disable this component.
     * @return {Ext.Component} this
     */
    ,disable:function() {
        if(this.isRendered) {
            this.df.disabled = this.disabled;
            this.df.onDisable();
            this.tf.onDisable();
        }
        this.disabled = true;
        this.df.disabled = true;
        this.tf.disabled = true;
        this.fireEvent("disable", this);
        return this;
    } // eo function disable
    // }}}
    // {{{
    /**
     * Enable this component.
     * @return {Ext.Component} this
     */
    ,enable:function() {
        if(this.rendered){
            this.df.onEnable();
            this.tf.onEnable();
        }
        this.disabled = false;
        this.df.disabled = false;
        this.tf.disabled = false;
        this.fireEvent("enable", this);
        return this;
    } // eo function enable
    // }}}
    // {{{
    /**
     * private Focus date filed
     */
    ,focus:function() {
        this.df.focus();
    } // eo function focus
    // }}}
    // {{{
    /**
     * private
     */
    ,getPositionEl:function() {
        return this.wrap;
    }
    // }}}
    // {{{
    /**
     * private
     */
    ,getResizeEl:function() {
        return this.wrap;
    }
    // }}}
    // {{{
    /**
     * @return {Date/String} Returns value of this field
     */
    ,getValue:function() {
        // create new instance of date
        return this.dateValue ? new Date(this.dateValue) : '';
    } // eo function getValue
    // }}}
    // {{{
    /**
     * @return {Boolean} true = valid, false = invalid
     * private Calls isValid methods of underlying DateField and TimeField and returns the result
     */
    ,isValid:function() {
        return this.df.isValid() && this.tf.isValid();
    } // eo function isValid
    // }}}
    // {{{
    /**
     * Returns true if this component is visible
     * @return {boolean} 
     */
    ,isVisible : function(){
        return this.df.rendered && this.df.getActionEl().isVisible();
    } // eo function isVisible
    // }}}
    // {{{
    /** 
     * private Handles blur event
     */
    ,onBlur:function(f) {
        // called by both DateField and TimeField blur events

        // revert focus to previous field if clicked in between
        if(this.wrapClick) {
            f.focus();
            this.wrapClick = false;
        }

        // update underlying value
        if(f === this.df) {
            this.updateDate();
        }
        else {
            this.updateTime();
        }
        this.updateHidden();

        // fire events later
        (function() {
            if(!this.df.hasFocus && !this.tf.hasFocus) {
                var v = this.getValue();
                if(String(v) !== String(this.startValue)) {
                    this.fireEvent("change", this, v, this.startValue);
                }
                this.hasFocus = false;
                this.fireEvent('blur', this);
            }
        }).defer(100, this);

    } // eo function onBlur
    // }}}
    // {{{
    /**
     * private Handles focus event
     */
    ,onFocus:function() {
        if(!this.hasFocus){
            this.hasFocus = true;
            this.startValue = this.getValue();
            this.fireEvent("focus", this);
        }
    }
    // }}}
    // {{{
    /**
     * private Just to prevent blur event when clicked in the middle of fields
     */
    ,onMouseDown:function(e) {
        if(!this.disabled) {
            this.wrapClick = 'td' === e.target.nodeName.toLowerCase();
        }
    }
    // }}}
    // {{{
    /**
     * private
     * Handles Tab and Shift-Tab events
     */
    ,onSpecialKey:function(t, e) {
        var key = e.getKey();
        if(key === e.TAB) {
            if(t === this.df && !e.shiftKey) {
                e.stopEvent();
                this.tf.focus();
            }
            if(t === this.tf && e.shiftKey) {
                e.stopEvent();
                this.df.focus();
            }
        }
        // otherwise it misbehaves in editor grid
        if(key === e.ENTER) {
            this.updateValue();
        }

    } // eo function onSpecialKey
    // }}}
    // {{{
    /**
     * private Sets the value of DateField
     */
    ,setDate:function(date) {
        this.df.setValue(date);
    } // eo function setDate
    // }}}
    // {{{
    /** 
     * private Sets the value of TimeField
     */
    ,setTime:function(date) {
        this.tf.setValue(date);
    } // eo function setTime
    // }}}
    // {{{
    /**
     * private
     * Sets correct sizes of underlying DateField and TimeField
     * With workarounds for IE bugs
     */
    ,setSize:function(w, h) {
        if(!w) {
            return;
        }
        if('below' === this.timePosition) {
            this.df.setSize(w, h);
            this.tf.setSize(w, h);
            if(Ext.isIE) {
                this.df.el.up('td').setWidth(w);
                this.tf.el.up('td').setWidth(w);
            }
        }
        else {
            this.df.setSize(w - this.timeWidth - 4, h);
            this.tf.setSize(this.timeWidth, h);

            if(Ext.isIE) {
                this.df.el.up('td').setWidth(w - this.timeWidth - 4);
                this.tf.el.up('td').setWidth(this.timeWidth);
            }
        }
    } // eo function setSize
    // }}}
    // {{{
    /**
     * @param {Mixed} val Value to set
     * Sets the value of this field
     */
    ,setValue:function(val) {
        if(!val && true === this.emptyToNow) {
            this.setValue(new Date());
            return;
        }
        else if(!val) {
            this.setDate('');
            this.setTime('');
            this.updateValue();
            return;
        }
        if ('number' === typeof val) {
          val = new Date(val);
        }
        val = val ? val : new Date(1970, 0 ,1, 0, 0, 0);
        var da, time;
        if(val instanceof Date) {
            this.setDate(val);
            this.setTime(val);
            this.dateValue = new Date(val);
        }
        else {
            da = val.split(this.dtSeparator);
            this.setDate(da[0]);
            if(da[1]) {
                this.setTime(da[1]);
            }
        }
        this.updateValue();
    } // eo function setValue
    // }}}
    // {{{
    /**
     * Hide or show this component by boolean
     * @return {Ext.Component} this
     */
    ,setVisible: function(visible){
        if(visible) {
            this.df.show();
            this.tf.show();
        }else{
            this.df.hide();
            this.tf.hide();
        }
        return this;
    } // eo function setVisible
    // }}}
    //{{{
    ,show:function() {
        return this.setVisible(true);
    } // eo function show
    //}}}
    //{{{
    ,hide:function() {
        return this.setVisible(false);
    } // eo function hide
    //}}}
    // {{{
    /**
     * private Updates the date part
     */
    ,updateDate:function() {

        var d = this.df.getValue();
        if(d) {
            if(!(this.dateValue instanceof Date)) {
                this.initDateValue();
                if(!this.tf.getValue()) {
                    this.setTime(this.dateValue);
                }
            }
            this.dateValue.setMonth(0); // because of leap years
            this.dateValue.setFullYear(d.getFullYear());
            this.dateValue.setMonth(d.getMonth());
            this.dateValue.setDate(d.getDate());
        }
        else {
            this.dateValue = '';
            this.setTime('');
        }
    } // eo function updateDate
    // }}}
    // {{{
    /**
     * private
     * Updates the time part
     */
    ,updateTime:function() {
        var t = this.tf.getValue();
        if(t && !(t instanceof Date)) {
            t = Date.parseDate(t, this.tf.format);
        }
        if(t && !this.df.getValue()) {
            this.initDateValue();
            this.setDate(this.dateValue);
        }
        if(this.dateValue instanceof Date) {
            if(t) {
                this.dateValue.setHours(t.getHours());
                this.dateValue.setMinutes(t.getMinutes());
                this.dateValue.setSeconds(t.getSeconds());
            }
            else {
                this.dateValue.setHours(0);
                this.dateValue.setMinutes(0);
                this.dateValue.setSeconds(0);
            }
        }
    } // eo function updateTime
    // }}}
    // {{{
    /**
     * private Updates the underlying hidden field value
     */
    ,updateHidden:function() {
        if(this.isRendered) {
            var value = this.dateValue instanceof Date ? this.dateValue.format(this.hiddenFormat) : '';
            this.el.dom.value = value;
        }
    }
    // }}}
    // {{{
    /**
     * private Updates all of Date, Time and Hidden
     */
    ,updateValue:function() {

        this.updateDate();
        this.updateTime();
        this.updateHidden();

        return;
    } // eo function updateValue
    // }}}
    // {{{
    /**
     * @return {Boolean} true = valid, false = invalid
     * callse validate methods of DateField and TimeField
     */
    ,validate:function() {
        return this.df.validate() && this.tf.validate();
    } // eo function validate
    // }}}
    // {{{
    /**
     * Returns renderer suitable to render this field
     * @param {Object} Column model config
     */
    ,renderer: function(field) {
        var format = field.editor.dateFormat || Ext.ux.form.DateTime.prototype.dateFormat;
        format += ' ' + (field.editor.timeFormat || Ext.ux.form.DateTime.prototype.timeFormat);
        var renderer = function(val) {
            var retval = Ext.util.Format.date(val, format);
            return retval;
        };
        return renderer;
    } // eo function renderer
    // }}}

}); // eo extend

// register xtype
Ext.reg('xdatetime', Ext.ux.form.DateTime);
