if (typeof POLAR == 'undefined' || !POLAR) {
    var POLAR = {};
}

POLAR.Reports = function() {};

// Creates a dialog with 2 calendars. Selectable interval is taken from query as 'startDate' and 'endDate'.
// @param buttonId - adds onclick event to button with id "buttonId", null to skip
// @param callbackFunction - after dates have been set, "callbackFunction(resultDates)" is called with date pick result as argument (use resultDates.startDate and resultDates.endDate)
// @note - what interval will calendar show is read from url, and if not avaliable this and last month are used
POLAR.Reports.createCalendar = function (buttonId, callbackFunction)
{
	var intervalDates = {};							// dates that define what months will the calendar display
	var buttonPosition = { top: 0, left: 0 };		// css top and left (x and y) position of button element, we need it to show the calendar there, just beside the button
	var calendarDialog;								// calendar dialog popup
	
	intervalDates.startDate = POLAR.Reports.getUrlParameter(location.href, 'startDate');
    if (intervalDates.startDate != null) {
		intervalDates.startDate = Date.parseExact(intervalDates.startDate, 'yyyy-MM-ddTHH:mm:ssZ');
		intervalDates.startDate.add({minutes: parseInt(TIME_ZONE_OFFSET_MINUTES)})
    }
  
    intervalDates.endDate = POLAR.Reports.getUrlParameter(location.href, 'endDate');
    if (intervalDates.endDate != null) {
		intervalDates.endDate = Date.parseExact(intervalDates.endDate, 'yyyy-MM-ddTHH:mm:ssZ');
		intervalDates.endDate.add({minutes: parseInt(TIME_ZONE_OFFSET_MINUTES)})
    }
	
	if (intervalDates.startDate == null || intervalDates.endDate == null) {    
		intervalDates.endDate = Date.today().add({ hours: 23, minutes: 59, seconds: 59 });
		intervalDates.startDate = Date.today().moveToFirstDayOfMonth();
    }
	// apply style to button and initialize calendar
	new YAHOO.widget.Button(buttonId);
	buttonPosition = $('#' + buttonId).offset();
	calendarDialog = POLAR.Reports.createYuiCalendar('yuiCalendarDialog', intervalDates, callbackFunction, buttonPosition.left - 295, buttonPosition.top + 30);

	// display calendar on click, fixed position left and below the button
	if (buttonId != null) {
		$('#' + buttonId).click(function() {
			if (calendarDialog.cfg.getProperty('visible') === false) {
				calendarDialog.show();
			} else {
				calendarDialog.hide();
			}
		});
	}
}

// Creates a yui IntervalCalendar and returns the dialog popup of it
// @containerID - id of container for the calendar dialog
// @intervalDates - .startDate and .endDate for the interval that will show as selected in the calendar dialog
// @positionX, @positionY - x,y absolute screen coordinates to display the calendar
// @callbackFunction - function to be called with result as argument
POLAR.Reports.createYuiCalendar = function (containerId, intervalDates, callbackFunction, positionX, positionY) {
	var calendar, dialog;
	
	if (!dialog) {

        /* Hide Calendar if we click anywhere in the document other than the calendar
        Event.on(document, "click", function(e) {
            var el = Event.getTarget(e);
            var dialogEl = dialog.element;
            if (el != dialogEl && !Dom.isAncestor(dialogEl, el) && el != showBtn && !Dom.isAncestor(showBtn, el)) {
                dialog.hide();
            }
        });
        */

        function applyHandler() {
          var resultDates = {};
		  var interval = calendar.getInterval();
          resultDates.startDate = interval[0];
          resultDates.endDate = new Date(interval[1]).add({ hours: 23, minutes: 59, seconds: 59 });
          dialog.hide();
          callbackFunction(resultDates);
        }

        function closeHandler() {
            dialog.hide();
        }

        dialog = new YAHOO.widget.Dialog(containerId, {
            visible:false,
            context:["show", "tl", "bl"],
            buttons:[ {text:"Apply", handler: applyHandler}, {text:"Close", handler: closeHandler}],
            draggable:false
        });
        
        dialog.setHeader('Please make a selection:');
        dialog.setBody('<div id="reportCalendar"></div>');
        dialog.render(document.body);
	    dialog.moveTo(positionX, positionY);

        dialog.showEvent.subscribe(function() {
            if (YAHOO.env.ua.ie) {
                // Since we're hiding the table using yui-overlay-hidden, we
                // want to let the dialog know that the content size has changed, when
                // shown
                dialog.fireEvent("changeContent");
            }
        });
    }

    // Lazy Calendar Creation - Wait to create the Calendar until the first time the button is clicked.
    if (!calendar) {
         /**
         * IntervalCalendar is an extension of the CalendarGroup designed  specifically
         * for  the selection of an interval of dates.
         *
         * @namespace YAHOO.example.calendar
         * @module calendar
         * @since 2.5.2
         * @requires  yahoo, dom, event, calendar
         */
         
         /**
         * IntervalCalendar is an extension of the CalendarGroup designed  specifically
         * for the selection of an interval of dates, as opposed to a  single date or
         * an arbitrary collection of dates.
         * <p>
         * <b>Note:</b> When using IntervalCalendar, dates  should not be selected or
         * deselected using the 'selected' configuration property or any of  the
         * CalendarGroup select/deselect methods. Doing so will corrupt the  internal
         * state of the control. Instead, use the provided methods  setInterval and
         *  resetInterval.
         *  </p>
         * <p>
         * Similarly, when handling select/deselect/etc. events, do not use  the
         * dates passed in the arguments to attempt to keep track of the  currently
         * selected interval. Instead, use getInterval.
         * </p>
         *
         * @namespace  YAHOO.example.calendar
         * @class  IntervalCalendar
         * @extends  YAHOO.widget.CalendarGroup
         *  @constructor
         * @param {String | HTMLElement} container The id of, or reference  to, an HTML DIV element which will contain the control.
         *  @param {Object} cfg optional The initial configuration options for the  control.
         */
         function IntervalCalendar(container, cfg) {
           /**
           *  The interval state, which counts the number of interval endpoints that  have
           * been selected (0 to 2).
           *
           * @private
           * @type Number
           */
           this._iState = 0;
           
           // Must be a multi-select  CalendarGroup
           cfg = cfg || {};
           cfg.multi_select = true;
           
           // Call parent constructor
           IntervalCalendar.superclass.constructor.call(this, container, cfg);
           
           // Subscribe internal event  handlers
           this.beforeSelectEvent.subscribe(this._intervalOnBeforeSelect, this, true);
           this.selectEvent.subscribe(this._intervalOnSelect, this, true);
           this.beforeDeselectEvent.subscribe(this._intervalOnBeforeDeselect, this, true);
           this.deselectEvent.subscribe(this._intervalOnDeselect, this, true);
         }
         
         /**
         * Default configuration  parameters.
         *
         * @property  IntervalCalendar._DEFAULT_CONFIG
         * @final
         * @static
         * @private
         * @type Object
         */
         IntervalCalendar._DEFAULT_CONFIG = YAHOO.widget.CalendarGroup._DEFAULT_CONFIG;
         
         YAHOO.lang.extend(IntervalCalendar, YAHOO.widget.CalendarGroup, {  
           /**
           *  Returns a string representation of a date which takes into account
           *  relevant localization settings and is suitable for use with
           *  YAHOO.widget.CalendarGroup and YAHOO.widget.Calendar methods.
           *
           * @method  _dateString
           * @private
           *  @param {Date} d The JavaScript Date object of which to obtain a string  representation.
           *  @return {String} The string representation of the JavaScript Date  object.
           */
           _dateString : function(d) {
             var  a = [];
             a[this.cfg.getProperty(IntervalCalendar._DEFAULT_CONFIG.MDY_MONTH_POSITION.key)-1] = (d.getMonth() + 1);
             a[this.cfg.getProperty(IntervalCalendar._DEFAULT_CONFIG.MDY_DAY_POSITION.key)-1] = d.getDate();
             a[this.cfg.getProperty(IntervalCalendar._DEFAULT_CONFIG.MDY_YEAR_POSITION.key)-1] = d.getFullYear();
             var s = this.cfg.getProperty(IntervalCalendar._DEFAULT_CONFIG.DATE_FIELD_DELIMITER.key);
             return  a.join(s);
           },
           
           /**
           *  Given a lower and upper date, returns a string representing the  interval
           *  of dates between and including them, which takes into account relevant
           *  localization settings and is suitable for use with
           *  YAHOO.widget.CalendarGroup and YAHOO.widget.Calendar methods.
           * <p>
           *  <b>Note:</b> No internal checking is done to ensure that the lower  date
           * is in fact  less than or equal to the upper date.
           * </p>
           *
           * @method  _dateIntervalString
           * @private
           *  @param {Date} l The lower date of the interval, as a JavaScript Date  object.
           *  @param {Date} u The upper date of the interval, as a JavaScript Date  object.
           *  @return {String} The string representing the interval of dates between  and
           *                    including the lower and upper dates.
           */
           _dateIntervalString  : function(l, u) {
             var s = this.cfg.getProperty(IntervalCalendar._DEFAULT_CONFIG.DATE_RANGE_DELIMITER.key);
             return  (this._dateString(l) + s + this._dateString(u));
           },
           
           /**
           *  Returns the lower and upper dates of the currently selected interval, if  an
           * interval is selected.
           *
           * @method  getInterval
           * @return {Array} An empty array if no interval is selected;  otherwise an array
           *                  consisting of two JavaScript Date objects, the first being  the
           *                  lower date of the interval and the second being the upper  date.
           */
           getInterval : function() {
             // Get selected dates
             var dates = this.getSelectedDates();
             if(dates.length > 0) {
               // Return lower and upper  date in array
               var l = dates[0];
               var u = dates[dates.length - 1];
               return [l, u];
             }
             else {
               // No dates selected,  return empty array
               return [];
             }
           },
           
           /**
           *  Sets the currently selected interval by specifying the lower and upper
           * dates of the interval  (in either order).
           * <p>
           *  <b>Note:</b> The render method must be called after setting the  interval
           * for any changes to be  seen.
           * </p>
           *
           * @method  setInterval
           *  @param {Date} d1 A JavaScript Date object.
           *  @param {Date} d2 A JavaScript Date object.
           */
           setInterval : function(d1, d2) {
             // Determine lower and upper  dates
             var b = (d1 <= d2);
             var l = b ? d1 : d2;
             var  u = b ? d2 : d1;
             // Update configuration
             this.cfg.setProperty('selected', this._dateIntervalString(l, u), false);
             this._iState = 2;
           },
           
           /**
           * Resets the currently  selected interval.
           * <p>
           *  <b>Note:</b> The render method must be called after resetting the  interval
           * for any changes to be  seen.
           * </p>
           *
           * @method  resetInterval
           */
           resetInterval : function() {
             // Update  configuration
             this.cfg.setProperty('selected', [], false);
             this._iState = 0;
           },
           
           /**
           * Handles beforeSelect  event.
           *
           * @method  _intervalOnBeforeSelect
           * @private
           */
           _intervalOnBeforeSelect  : function(t,a,o) {
             // Update interval state
             this._iState = (this._iState + 1) % 3;
             if(this._iState == 0) {
               //  If starting over with upcoming selection, first deselect all
               this.deselectAll();
               this._iState++;
             }
           },
           
           /**
           * Handles selectEvent  event.
           *
           * @method  _intervalOnSelect
           * @private
           */
           _intervalOnSelect : function(t,a,o) {
             // Get selected dates
             var dates = this.getSelectedDates();
             if(dates.length > 1) {
               /*  If more than one date is selected, ensure that the entire interval
               between and including  them is selected */
               var l = dates[0];
               var u = dates[dates.length - 1];
               this.cfg.setProperty('selected', this._dateIntervalString(l, u), false);
             }
             // Render changes
             this.render();
           },
           
           /**
           * Handles beforeDeselect  event.
           *
           * @method  _intervalOnBeforeDeselect
           * @private
           */
           _intervalOnBeforeDeselect  : function(t,a,o) {
             if(this._iState != 0) {
               /*  If part of an interval is already selected, then swallow up
               this  event because it is superfluous (see _intervalOnDeselect) */
               return false;
             }
           },
           
           /**
           * Handles  deselectEvent event.
           *
           * @method  _intervalOnDeselect
           * @private
           */
           _intervalOnDeselect  : function(t,a,o) {
             if(this._iState != 0) {
               //  If part of an interval is already selected, then first deselect all
               this._iState = 0;
               this.deselectAll();
               
               // Get  individual date deselected and page containing it
               var d = a[0][0];
               var date = YAHOO.widget.DateMath.getDate(d[0], d[1] - 1, d[2]);
               var page = this.getCalendarPage(date);
               if(page) {
                 // Now (re)select the  individual date
                 page.beforeSelectEvent.fire();
                 this.cfg.setProperty('selected', this._dateString(date), false);
                 page.selectEvent.fire([d]);
               }
               // Swallow up  since we called deselectAll above
               return false;
             }
           }
         });    
                        
         
         YAHOO.namespace("calendar");
         YAHOO.calendar.IntervalCalendar = IntervalCalendar;
         
         // Initialise calendar
         calendar = new YAHOO.calendar.IntervalCalendar("reportCalendar", {pages:2});
         
         // Listener to show the 2 page Calendar when the button is clicked
         // YAHOO.util.Event.addListener("showCalendar", "click", cal.show, cal, true);
         
         // Change Monday for first day of the week
         calendar.cfg.setProperty("start_weekday", "1");
         
         // Sets first displayed month
         calendar.cfg.setProperty("pagedate", Date.today().add({months: -1}).toString("M/yyyy"));
         
         // Sets the Calendar's maximum selectable date
         calendar.cfg.setProperty("maxdate", Date.today().toString("M/d/yyyy"));
         
         // Attach update contols even2t handeler
         //cal.selectEvent.subscribe(updateControls , cal, true);
      
         calendar.setInterval(intervalDates.startDate, intervalDates.endDate);
         
         calendar.render();
    }
	
	return dialog;
}

//-------------------------------------------------------------------------------------
/*
* Fetches argumenst from passed url
*
* myurl = current url
* name = argument name to fetch
*
* Note: return null if nothing found
*/
POLAR.Reports.getUrlParameter = function (myurl, name) {
	var argumentsStart = myurl.indexOf('?');
	if (argumentsStart != -1) {
		var arguments = myurl.substring(argumentsStart + 1, myurl.length);
		var startPosition = arguments.indexOf(name);
		if (arguments != '' && startPosition != -1){
			var startPosition = startPosition + name.length + 1;
			var endPosition = arguments.indexOf('&',startPosition);
			if (endPosition == -1){
				endPosition = arguments.length;                
			}
			return arguments.substring(startPosition, endPosition);
		}
	}
	
	return null;
}

// creates a table with data
// @param containerId - id of html container, a div is fine
// @param columnDefinitnion - defines key names, column names, data: { key, label, responseSchemaKey }
// @param data - array data source for the table, it must have varibales identical to keys in column definition
POLAR.Reports.createTable = function (containerId, columnDefinition, data) {
	var myResponseSchema = {fields: []};
	var myColumnDefinitions = [];
	
	for (var i = 0; i < columnDefinition.length; i++) {
		myResponseSchema.fields[i] = { key: columnDefinition[i].responseSchemaKey };
		myColumnDefinitions[i] = { key: columnDefinition[i].key, label: columnDefinition[i].label };
	}
	
	var myDataSource = new YAHOO.util.DataSource(data);
	myDataSource.responseType = YAHOO.util.DataSource.TYPE_JSARRAY;   
	myDataSource.responseSchema = myResponseSchema;
	var myDataTable = new YAHOO.widget.DataTable(containerId, myColumnDefinitions, myDataSource);
}

// returns calculated result from server side java script
POLAR.Reports.getServerSideResult = function() {
	var objJsonData = YAHOO.lang.JSON.parse(resource.Data);
	var objJsonResult  = YAHOO.lang.JSON.parse(objJsonData.JsonResult);

	return objJsonResult;
}

// converts array of IDs to href with incident number as text
// e.g. [0,1,2] => '<a href=".../incidents?ids=0;1;2;">3</a>'
// @IDArray - array of incident IDs
// @return - html <a> tag
POLAR.Reports.convertIDArrayToLink = function (IDArray) {
	var incidentNumberString = '0';
	
	if (IDArray.length > 0) {
		var queryString = '';
		for (var i = 0; i < IDArray.length; i++) {
			queryString += IDArray[i] + ';';
		}
		
		queryString = queryString.slice(0, -1);
		queryString = '?id=' + queryString;
				   
		incidentNumberString = '<a href="' + POLAR.Reports.getBaseUri(location.href) + 'incidents' + queryString + '">' + IDArray.length + '</a>';
	}
	
	return incidentNumberString;
}

// returns report base uri
// e.g. "http://www.domain.com/app/report/12345?query" => "http://www.domain.com/app/"
POLAR.Reports.getBaseUri = function(myUri) {
	var end = myUri.indexOf('report');
	return myUri.substring(0, end);
}

// updates text on element to represent start date and end date text in user's format
// e.g. 12/31/2009 - 01/01/2010
POLAR.Reports.updateIntervalText = function (elementId, startDate, endDate) {
    var startTxt = POLAR.View.DateTime.dateToString(startDate);
    var endTxt = POLAR.View.DateTime.dateToString(endDate);
    $(elementId).text(startTxt + " - " + endTxt + "   ");
}
