﻿// used by TransferResults.aspx and its drilldown reports
// this is compatible with only TransferResults.aspx which generates
// grids/reports based on TansferQueryBuilder.aspx
// this needs TransferFormatData.js & Prototype.js & jQuery

/**
Class to represent Map
@constructor
*/
function MapPanel(settings) { this.init(settings); }
/**Google map object*/
MapPanel.prototype.map = null;
MapPanel.prototype.id = null;
MapPanel.prototype.name = null;
/**Map current zoom level*/
MapPanel.prototype.zoomLevel = null;
/**Center*/
MapPanel.prototype.center = null;
/**Markers on the map*/
MapPanel.prototype.markers = new Array();
/**Geocoder to find the geocode values*/
MapPanel.prototype.geocoder = null;
/**Map container*/
MapPanel.prototype.container = null;
/**Markers count*/
MapPanel.prototype.markerCount = 0;
/**Map latitude longitude bounds*/
MapPanel.prototype.latLngBounds = null;
/**
To keep a count of geco-coding request in process
*/
MapPanel.prototype.geoCodingCount = 0;
/**
Initializer

@param settings Initialize default settings
*/
MapPanel.prototype.init = function(settings) {
    // hide map container on load to avoid exatra white space after Summary Info for non-map reports
    jQuery('td#mapContainerTD').removeClass('displayNone'); ;

    this.id = settings.id;
    this.name = settings.name;
    this.container = settings.container;
    this.map = new GMap2(settings.container);
    this.map.addControl(new GSmallMapControl());
    this.map.addControl(new GMapTypeControl());
    //default coord. & zoom
    this.map.setCenter(new GLatLng(41.89, -87.63), 2);
    this.store = new Storage();
    this.culture = this.store.getCulture();
};

/**
Function to add marker

@param lat
@param lng
@param label Content is used to set the title abbribute for tooptip
@param minimizedContent
@param maximizedContent
@param completeAddress
*/
MapPanel.prototype.addMarker = function(lat, lng, label, minimizedContent, maximizedContent, completeAddress) {
	// configures & places marker(location) on the map

	var thisObj = this;
	var addMarkerNow = function(geoCodingCount) {
		if (thisObj.markerCount == 0)
			thisObj.latLngBounds = new GLatLngBounds(new GLatLng(lat, lng), new GLatLng(lat, lng));
		else
			thisObj.latLngBounds.extend(new GLatLng(lat, lng));

		thisObj.geoCodeLocation(lat, lng, label, minimizedContent, maximizedContent, thisObj.latLngBounds.getCenter(), thisObj.latLngBounds);
		thisObj.markerCount++;
		if (geoCodingCount == 0) { window.PageBus.publish('com.cec.map.geocoding.done', { results: thisObj.results, mapType: thisObj.mapType, mapObj: thisObj }); }
	};

	// if lat, lng values are invalid and completeAddress is valid then use Google geo-code to find new lat, lng values & then map it
	if (!this.isValidLatLng(lat, lng) && completeAddress != undefined && completeAddress.length > 0) {
		this.geocoder = new GClientGeocoder();
		this.geoCodingCount++;
		newThisObj = this;
		this.geocoder.getLocations(completeAddress, function(response) {
			if (!response || response.Status.code != 200) {
				//ignore if google could not geo code
			}
			else {
				lat = response.Placemark[0].Point.coordinates[1];
				lng = response.Placemark[0].Point.coordinates[0];
				newThisObj.geoCodingCount--;
				addMarkerNow(newThisObj.geoCodingCount);
			}
		});
	}
	else {
	    addMarkerNow(thisObj.geoCodingCount);
	}
};
/**
Function to geo-code location

@param lat
@param lng
@param label Content is used to set the title abbribute for tooptip
@param minContent
@param maxContent
@param center
@param latLngBounds
*/
MapPanel.prototype.geoCodeLocation = function(lat, lng, label, minContent, maxContent, center, latLngBounds) {
    // places marker with info window attribs
    if (this.map == null) {
        alert(Resource.alertMsg[this.culture]['browserNotGoogleMapsEnabled']);
        return false;
    }

    // do not place an invalid marker
    if (!this.isValidLatLng(lat, lng)) {
        return false;
    }

    var marker = this.createMarker(lat, lng, label, minContent, maxContent, center, latLngBounds);
    this.markers[this.markers.length] = marker;
    this.map.addOverlay(marker);

    // to reposition center & zoom level of the map, on closing google bubble window
    var themap = this;
    var justSetCenter = this.justSetCenter;
    var closecenter = this.center;
    var closezoomLevel = this.zoomlevel;
    var name = this.name;
    GEvent.addListener(this.map, "infowindowclose", function() {
        window.PageBus.publish("com.cec.map.infowindow.close", { mapPanel: themap });
    });
};

/**
Function to set center

@param center Center co-ordinates for the map
@param zoomLevel Zoom level for the map
*/
MapPanel.prototype.justSetCenter = function(center, zoomLevel) {
    this.map.setCenter(center, zoomLevel);
};

/**
Function to clear markers on the map
*/
MapPanel.prototype.clearMarkers = function() {
    for (var i = 0; i < this.markers.length; i++) this.map.removeOverlay(this.markers[i]);
    this.markers = new Array();
    this.latLngBounds = new Array();
    this.markerCount = 0;
};

/**
Function to create marker
*/
MapPanel.prototype.createMarker = function(lat, lng, label, minContent, maxContent, center, latLngBounds) {
    var opts = {
        'icon': icon,
        'clickable': true,
        'labelText': '',
        'title': label
    };

    var marker = new GMarker(new GLatLng(lat, lng), opts);
    this.setCenter(center, latLngBounds);

    var map = this.map;
    var culture = this.culture;
    GEvent.addListener(marker, 'click', function() {
        if (maxContent != null && maxContent.length > 0)
            marker.openInfoWindowHtml(minContent, { maxContent: maxContent, maxTitle: '<span id=infoWindowHeader>' + Resource.transfersAndReleases[culture] + '</span>' });
        else
            marker.openInfoWindowHtml(minContent);
        map.infoWindow = map.getInfoWindow();   // save clicked infoWindow to support hyperlink click to maximize
    });
    return marker;
};

/**
Function to maximize the info-window
*/
MapPanel.prototype.infoWindowMaximize = function() {
    // maximize info window; this is called in formatData.js
    this.map.infoWindow.maximize();
};

/**
Function to set center
*/
MapPanel.prototype.setCenter = function(center, bounds) {
    // sets center & zooms to show everything in bounds
    this.center = center;
    var zoomLevel = this.map.getBoundsZoomLevel(bounds);

    // set state level zoom
    if (zoomLevel > 6) zoomLevel = 6;

    this.zoomLevel = zoomLevel;
    this.map.setCenter(center, zoomLevel);
};

/**
Function to check if the co-ordinates are valid and fall within US/MX/CA region
*/
MapPanel.prototype.isValidLatLng = function(lat, lng) {
    // checks for a valid lat, lng

    var flag = true;

    try {
        if (lat == null || lng == null || isNaN(eval(lat)) || isNaN(eval(lng)) || !this.isWithInUSCAMX(lat, lng))
            flag = false;

    } catch (e) {
        flag = false;
    }
    return flag;
};

/**
Function to check if the co-ordinates fall with in US/MX/CA region
*/
MapPanel.prototype.isWithInUSCAMX = function(lat, lng) {
    // identifies lat, lng is with in US, CA & MX

    // boundary coordiantes for US, Canada & Mexico
    // http://nhdgeo.usgs.gov/metadata/stbdynabnd1mil.htm
    // WestBoundingCoordinate: -179.138657
    // EastBoundingCoordinate: -11.312319
    // NorthBoundingCoordinate: 83.627419
    // SouthBoundingCoordinate: 5.499074

    var ne = new GLatLng(83.627419, -11.312319);
    var sw = new GLatLng(5.499074, -179.138657);

    var flag = (new GLatLngBounds(sw, ne)).containsLatLng(new GLatLng(lat, lng));

    // American Samoa falls outside the above coordinates
    // appx. cooridnates found using http://www.geocodezip.com/PolygonTool.asp
    // sw : -14.382807,-170.860748
    // ne : -14.229776,-170.546265

    ne = new GLatLng(-14.229776, -170.546265);
    sw = new GLatLng(-14.382807, -170.860748);

    var islands = new GLatLngBounds(sw, ne);
    islands.extend(new GLatLng(18.149722, -66.299722)); // PR
    islands.extend(new GLatLng(15.2, 145.75)); // MP
    islands.extend(new GLatLng(13.45, 144.783333)); // GU
    islands.extend(new GLatLng(17.75, -64.75)); // VI

    if (!flag) flag = islands.containsLatLng(new GLatLng(lat, lng));
    return flag;
};

/**
Function to resize the map
*/
MapPanel.prototype.resize = function(width, height) {
    var mapDivs = jQuery('.mapDiv');
    for (var i = 0; i < mapDivs.length; i++) {
        var mapDiv = mapDivs[i];
        $(mapDiv).setStyle({ width: width, height: height });
        if (MapManager.FacilityMap) MapManager.FacilityMap.map.checkResize();
        if (MapManager.StateMap) MapManager.StateMap.map.checkResize();
        if (MapManager.RecipientMap) MapManager.RecipientMap.map.checkResize();
        if (MapManager.RecipientStateMap) MapManager.RecipientStateMap.map.checkResize();
    }
};


/**
Class to represent Map Manager
@constructor
*/
function MapManager(settings) { this.init(settings); }

MapManager.prototype.updateMarkerInfo = function(subj, msg, data) {
	var data = new Array();
	data['count'] = msg.mapObj.markerCount;
	data['end'] = msg.mapObj.results.EndIndex;
	data['start'] = msg.mapObj.results.EndIndex > 0 ? msg.mapObj.results.StartIndex : 0;
	data['total'] = msg.mapObj.results.QueryCount;
	this.updateInfo(data, msg.mapObj.mapType);
};
/**
Initializer

@param settings Initialize with default values
*/
MapManager.prototype.init = function(settings) {
    if (!GBrowserIsCompatible()) return;
    if (!settings.mapContainerId) return;

    this.culture = settings.culture;
    this.mapContainerId = settings.mapContainerId;
    this.mapContainer = $(this.mapContainerId);
    if (!this.mapContainer) return;

    // google map key should be registered for this host
    // alert(window.location.host);
    // google map key should be registered for this host

    this.mapContainer.style.display = 'block';
    this.geocoder = new GClientGeocoder();
    this.center = null;
    this.zoomLevel = null;
    this.infoWindow = null;
    this.showDataLabel = Resource.showTransferAndReleaseData[this.culture];

    this.latLngBounds = null;   // stores boundary when more than one location is geoCoded & to find center, zoom level
    window.PageBus.subscribe('com.cec.data.Facility', this, this.loadFacilityData, { reportType: 'Facility', mapDiv: 'FacilityMap' });
    window.PageBus.subscribe('com.cec.data.State', this, this.loadStateData, { reportType: 'State', mapDiv: 'StateMap' });
    window.PageBus.subscribe('com.cec.data.Recipient', this, this.loadRecipientData, { reportType: 'Recipient', mapDiv: 'RecipientMap' });
    window.PageBus.subscribe('com.cec.data.RecipientState', this, this.loadRecipientStateData, { reportType: 'RecipientState', mapDiv: 'RecipientStateMap' });
    window.PageBus.subscribe('com.cec.map.infowindow.close', this, this.handleInfoWindowClose, null);
    window.PageBus.subscribe('com.cec.map.infowindow.open', this, this.handleInfoWindowOpen, null);
    window.PageBus.subscribe('com.cec.map.resize', this, this.resize, null);
    window.PageBus.subscribe('com.cec.map.select', this, this.select, null);
    window.PageBus.subscribe('com.cec.map.geocoding.done', this, this.updateMarkerInfo);

    var mapDivs = jQuery('.mapDiv');
    for (var i = 0; i < mapDivs.length; i++) {
        var mapDiv = mapDivs[i];
        switch (mapDiv.id) {
            case 'StateMap':
                this.StateMap = new MapPanel({ id: 'State', name: 'StateMap', container: mapDiv });
                break;
            case 'RecipientStateMap':
                this.RecipientStateMap = new MapPanel({ id: 'RecipientState', name: 'RecipientStateMap', container: mapDiv });
                break;
            case 'RecipientMap':
                this.RecipientMap = new MapPanel({ id: 'Recipient', name: 'RecipientMap', container: mapDiv });
                break;
            case 'FacilityMap':
                this.FacilityMap = new MapPanel({ id: 'Facility', name: 'FacilityMap', container: mapDiv });
                break;
        }
    }
    var selectedLi = jQuery('#mapsContainer li.selected')[0];
    switch (selectedLi.id) {
        case 'StateMapButton':
            this.selected = this.StateMap;
            break;
        case 'FacilityMapButton':
            this.selected = this.FacilityMap;
            break;
        case 'RecipientStateMapButton':
            this.selected = this.RecipientStateMap;
            break;
        case 'RecipientMapButton':
            this.selected = this.RecipientMap;
            break;
    }
    this.select(null, this.selected.id, null);
};
MapManager.prototype.showDataLabel = null;
MapManager.prototype.FacilityMap = null;
MapManager.prototype.StateMap = null;
MapManager.prototype.RecipientMap = null;
MapManager.prototype.RecipientStateMap = null;
MapManager.prototype.selected = null;
MapManager.prototype.facilityData = null;
MapManager.prototype.stateData = null;
MapManager.prototype.recipientData = null;
MapManager.prototype.recipientStateData = null;
MapManager.prototype.markerInfo = new Array();
/**
Function to select a map
*/
MapManager.prototype.select = function(subj, msg, data) {
    function hide(mapPanel) {
        jQuery(mapPanel.container).hide();
        jQuery('#' + mapPanel.container.id + 'Info').hide();
        jQuery('#' + mapPanel.container.id + 'Button').removeClass('selected');
    }
    function show(mapPanel) {
        jQuery(mapPanel.container).show();
        jQuery('#' + mapPanel.container.id + 'Info').show();
        jQuery('#' + mapPanel.container.id + 'Button').addClass('selected');

        if (mapPanel.map != null) mapPanel.map.checkResize();
        if (mapPanel.center != null) mapPanel.setCenter(mapPanel.center, mapPanel.latLngBounds);
    }

    if (this.StateMap) hide(this.StateMap);
    if (this.FacilityMap) hide(this.FacilityMap);
    if (this.RecipientMap) hide(this.RecipientMap);
    if (this.RecipientStateMap) hide(this.RecipientStateMap);

    switch (msg) {
        case 'State':
            show(this.StateMap);
            this.selected = this.StateMap;
            break;
        case 'Facility':
            show(this.FacilityMap);
            this.selected = this.FacilityMap;
            break;
        case 'RecipientState':
            show(this.RecipientStateMap);
            this.selected = this.RecipientStateMap;
            break;
        case 'Recipient':
            show(this.RecipientMap);
            this.selected = this.RecipientMap;
            break;
    }
};

/**
Function to handle map resize
*/
MapManager.prototype.resize = function(subj, msg, data) {
	var s = jQuery(msg.source);
	var newButtonLabel = "";
	var expand = false;
	var panelHeight, panelWidth;
	var con = $(this.mapContainerId);
	if (s.text() == msg.max) {
		//expanding
		newButtonLabel = msg.min;
		expand = true;

		// set map's new width and height
		panelWidth = (Global.getViewportWidth() - 50) + 'px';
		panelHeight = (Global.getViewportHeight() - 60) + 'px';
		con.setStyle({ zIndex: 999, position: 'absolute', width: panelWidth, height: panelHeight });

		var _top = Global.get_popup_top(con);
		var _left = Global.get_popup_left(con);
		con.setStyle({ zIndex: 999, position: 'absolute', top: _top, left: _left, width: panelWidth, height: panelHeight });

	} else {
		//shrinking
		newButtonLabel = msg.max;
		con.setStyle({ zIndex: 996, position: 'absolute', top: '0px', left: '0px' });
		con.setStyle({ position: 'relative', width: '362px', height: '333px' });
		panelWidth = '360px';
		panelHeight = '300px';
	}
	s.text(newButtonLabel);

	var mapDivs = jQuery('.mapDiv');
	for (var i = 0; i < mapDivs.length; i++) {
		var mapDiv = mapDivs[i];
		$(mapDiv).setStyle({ width: panelWidth, height: panelHeight });
	}

	var origSelected = this.selected;
	if (this.FacilityMap != null) {
		this.select(null, 'Facility');
		if (this.FacilityMap.map != null) this.FacilityMap.map.checkResize();
		if (this.FacilityMap.center != null) this.FacilityMap.setCenter(this.FacilityMap.center, this.FacilityMap.latLngBounds);
	}
	if (this.StateMap != null) {
		this.select(null, 'State');
		if (this.StateMap.map != null) this.StateMap.map.checkResize();
		if (this.StateMap.center != null) this.StateMap.setCenter(this.StateMap.center, this.StateMap.latLngBounds);
	}
	if (this.RecipientMap != null) {
		this.select(null, 'Recipient');
		if (this.RecipientMap.map != null) this.RecipientMap.map.checkResize();
		if (this.RecipientMap.center != null) this.RecipientMap.setCenter(this.RecipientMap.center, this.RecipientMap.latLngBounds);
	}
	if (this.RecipientStateMap != null) {
		this.select(null, 'RecipientState');
		if (this.RecipientStateMap.map != null) this.RecipientStateMap.map.checkResize();
		if (this.RecipientStateMap.center != null) this.RecipientStateMap.setCenter(this.RecipientStateMap.center, this.RecipientStateMap.latLngBounds);
	}
	this.select(null, origSelected.id);
};

/**
Function to handle info window close event
*/
MapManager.prototype.handleInfoWindowClose = function(subj, msg, data) {
    var center = msg.mapPanel.center;
    var zoom = msg.mapPanel.zoomLevel;
    msg.mapPanel.justSetCenter(center, zoom);
};

/**
Function to handle info window open event
*/
MapManager.prototype.handleInfoWindowOpen = function(subj, msg, data) {
    if (this[msg]) {
        this.currentInfoWindow = this[msg];
        this[msg].infoWindowMaximize();
    }
};

/**
Function to get info window minimized content

@param header Info window header
@param mapPanelName Name of the map panel
*/
MapManager.prototype.getMinimizedContent = function(header, mapPanelName) {
    return '<p id=infoWindowMinimizedContent>' + header + '<br/>' +
        '<a id="mediaDataToggler" class=handStyle ' +
        'onclick="window.PageBus.publish(\'com.cec.map.infowindow.open\',\'' + mapPanelName + '\');">' + this.showDataLabel + '</a></p>';
};

/**
Function to get info window maximized content

@param header Info window header
@param id Identifier of the marker
@param mapTables Data formated into tables for easy access using id
*/
MapManager.prototype.getMaximizedContent = function(header, id, mapTables) {
    //TODO: resource string "Media Type"
    var strId = id + '';
    var content = '<div id="bubbleContent"><div id="infoWindowMaximizedContent" class=alignLeft>' + header + '</div><br/><div id="mediaDataTableContainer">';
    for (var i = 0; i < mapTables.length; i++) {
        var mapTable = mapTables[i];
        if (mapTable.id == strId) {
            content += mapTable.table;
        }
    }
    content += '</div></div>';
    return content;
};

/**
Function to add delay
*/
MapManager.prototype.Sleep = function(naptime) {
    naptime = naptime * 1000;
    var sleeping = true;
    var now = new Date();
    var alarm;
    var startingMSeconds = now.getTime();
    while (sleeping) {
        alarm = new Date();
        alarmMSeconds = alarm.getTime();
        if (alarmMSeconds - startingMSeconds > naptime) { sleeping = false; }
    }
};

/**
Function to load facility data
*/
MapManager.prototype.loadFacilityData = function(subj, results, data) {
	this.FacilityMap.results = results; //this is required; used in 'com.cec.map.geocoding.done' event hanlder, which is updateMarkerInfo
	this.FacilityMap.mapType = 'facility';

	//results is a CEC.Domain.Reports.Report object, serialized
	this.FacilityMap.clearMarkers();
	for (var i = 0; i < results.Records.length; i++) {
		var facility = results.Records[i];
		var header = Resource.prtrId[this.culture] + ' ' + facility.PrTrId + '<br/>' +
                        facility.Name + '<br/>' +
                        facility.City + ', ' + facility.State + ', ' +
                        facility.Country;

		//address for google geo-coding if lat, lng values not available
		var completeAddress = this.cleanAddress(facility.Address) + this.clean(facility.City) + this.clean(facility.State) + this.clean(facility.Country);
		completeAddress = completeAddress.substring(completeAddress.length - 2, completeAddress.length - 1) == ',' ? completeAddress.substring(0, completeAddress.length - 2) : completeAddress;

		var minimized = this.getMinimizedContent(header, this.FacilityMap.name)
		var maximized = this.getMaximizedContent(header, facility.Id, results.MapTables);
		this.FacilityMap.addMarker(facility.Latitude, facility.Longitude, facility.Num + ' - ' + facility.Name.split('&nbsp;<span')[0], minimized, maximized, completeAddress);
	}
	if (this.FacilityMap.geoCodingCount == 0) { window.PageBus.publish('com.cec.map.geocoding.done', { results: this.results, mapType: this.mapType, mapObj: this.FacilityMap }); }

	this.FacilityMap.map.checkResize();
	this.FacilityMap.setCenter(this.FacilityMap.center, this.FacilityMap.latLngBounds);
};

var index = { facility:0, state:1, recipient:2, recipientState:3 }
/**
Function to update info
*/
MapManager.prototype.updateInfo = function(data, mapType, count) {
    var info = Resource.markerCountInfoText[this.culture][mapType];
    info = info.replace('$COUNT$', data['count']);
    info = info.replace('$1$', data['start']);
    info = info.replace('$2$', data['end']);
    info = info.replace('$TOTAL$', data['total']);

    var mapId = mapType.substring(0, 1).toUpperCase() + mapType.substring(1, mapType.length);
    jQuery('#' + mapId + 'MapInfo').html(info);
};

/**
Function to load recipient data
*/
MapManager.prototype.loadRecipientData = function(subj, results, data) {
	this.RecipientMap.results = results; //this is required; used in 'com.cec.map.geocoding.done' event hanlder, which is updateMarkerInfo
	this.RecipientMap.mapType = 'recipient';

	//results is a CEC.Domain.Reports.Report object, serialized
	this.RecipientMap.clearMarkers();
	for (var i = 0; i < results.Records.length; i++) {
		var facility = results.Records[i];
		var header = facility.Name + '<br/>' +
                     facility.City + ', ' + facility.State + ', ' +
                     facility.Country;

		//address for google geo-coding if lat, lng values not available
		var completeAddress = this.cleanAddress(facility.Address) + this.clean(facility.City) + this.clean(facility.State) + this.clean(facility.Country);
		completeAddress = completeAddress.substring(completeAddress.length - 2, completeAddress.length - 1) == ',' ? completeAddress.substring(0, completeAddress.length - 2) : completeAddress;

		var minimized = this.getMinimizedContent(header, this.RecipientMap.name)
		var maximized = this.getMaximizedContent(header, facility.Id, results.MapTables);
		this.RecipientMap.addMarker(facility.Latitude, facility.Longitude, facility.Num + ' - ' + facility.Name, minimized, maximized, completeAddress);
	}
	if (this.RecipientMap.geoCodingCount == 0) { window.PageBus.publish('com.cec.map.geocoding.done', { results: results, mapType: this.mapType, mapObj: this.RecipientMap }); }

	this.RecipientMap.checkResize();
	this.RecipientMap.setCenter(this.RecipientMap.center, this.RecipientMap.latLngBounds);
};

/**
Function to load state data
*/
MapManager.prototype.loadStateData = function(subj, results, data) {
	this.StateMap.results = results; //this is required; used in 'com.cec.map.geocoding.done' event hanlder, which is updateMarkerInfo
	this.StateMap.mapType = 'state';

	this.StateMap.clearMarkers();
	for (var i = 0; i < results.Records.length; i++) {
		var state = results.Records[i];

		//state & country for google geo-coding if lat, lng values not available
		var stateAndCountry = this.clean(state.Name) + this.clean(state.Country);
		stateAndCountry = stateAndCountry.substring(stateAndCountry.length - 2, stateAndCountry.length - 1) == ',' ? stateAndCountry.substring(0, stateAndCountry.length - 2) : stateAndCountry;

		var minimized = this.getMinimizedContent(state.Name, this.StateMap.name)
		var maximized = this.getMaximizedContent(state.Name, state.Id, results.MapTables);
		this.StateMap.addMarker(state.Latitude, state.Longitude, state.Num + ' - ' + state.Name, minimized, maximized, stateAndCountry);
	}
	if (this.StateMap.geoCodingCount == 0) { window.PageBus.publish('com.cec.map.geocoding.done', { results: results, mapType: this.mapType, mapObj: this.StateMap }); }

	this.StateMap.map.checkResize();
	this.StateMap.setCenter(this.StateMap.center, this.StateMap.latLngBounds);
};

/**
Function to load recipient state data
*/
MapManager.prototype.loadRecipientStateData = function(subj, results, data) {
	this.RecipientStateMap.results = results; //this is required; used in 'com.cec.map.geocoding.done' event hanlder, which is updateMarkerInfo
	this.RecipientStateMap.mapType = 'recipientState';

	this.RecipientStateMap.clearMarkers();
	for (var i = 0; i < results.Records.length; i++) {
		var state = results.Records[i];

		//state & country for google geo-coding if lat, lng values not available
		var stateAndCountry = this.clean(state.Name) + this.clean(state.Country);
		stateAndCountry = stateAndCountry.substring(stateAndCountry.length - 2, stateAndCountry.length - 1) == ',' ? stateAndCountry.substring(0, stateAndCountry.length - 2) : stateAndCountry;

		var minimized = this.getMinimizedContent(state.Name, this.RecipientStateMap.name)
		var maximized = this.getMaximizedContent(state.Name, state.Id, results.MapTables);
		this.RecipientStateMap.addMarker(state.Latitude, state.Longitude, state.Num + ' - ' + state.Name, minimized, maximized, stateAndCountry);
	}
	if (this.RecipientStateMap.geoCodingCount == 0) { window.PageBus.publish('com.cec.map.geocoding.done', { results: results, mapType: this.mapType, mapObj: this.RecipientStateMap }); }

	this.RecipientStateMap.map.checkResize();
	this.RecipientStateMap.setCenter(this.RecipientStateMap.center, this.RecipientStateMap.latLngBounds);
};

/**
Function to clean address

@param address Address to clean
*/
MapManager.prototype.cleanAddress = function(address) {
    address = jQuery.trim(address);
    return address.length > 0 ? address + ', ' : '';
};

/**
Function to clean the item

@param item Item to clean
*/
MapManager.prototype.clean = function(item) {
    item = jQuery.trim(item).toLowerCase();
    return item.length > 0 && item != 'unknown' && item != 'na' && item != 'n/a' ? item + ', ' : '';
};

/**
Class to represent Pager
@constructor
*/
function Pager(settings) {
    this.culture = settings.culture;
    this.containerId = settings.container;
    this.container = $(this.containerId);
    this.container.innerHTML = '';
    this.pageSize = settings.pagesize;
    this.currentPage = settings.pagenumber;
    this.queryCount = settings.querycount;
    this.totalPages = Math.ceil(this.queryCount / this.pageSize) - 1;
    this.pageNumbersToDisplay = 10;
    this.eventName = settings.pagerEvent;
    this.drawPaginator();
    this.store = settings.store;
    this.query = settings.query;
    
    //As pager gets created on paging & changing the page size, the pagesize subscription needs to be removed to avoid same event to be subscribed
    if (Resource.pageSizeSubscription[settings.container] != null) window.PageBus.unsubscribe(Resource.pageSizeSubscription[settings.container]);
    Resource.pageSizeSubscription[settings.container] = window.PageBus.subscribe('org.cec.pagesize.' + this.query.ResultTypeId + '.' + this.query.ReportTypeId, this, this.pageSizeHandler, null);
};

/**
Function to handle page size change event
*/
Pager.prototype.pageSizeHandler = function(subj, msg, data) {
    this.pageSize = jQuery('#' + msg.id).val();
    var evt = this.eventName;
    var curPage = this.currentPage = 0;
    this.store.setCookieValue(this.query.ResultTypeId + '.' + this.query.ReportTypeId, this.pageSize);
    window.PageBus.publish(evt, { button: curPage, pageSize: this.pageSize });
};

/**
Function to draw paginator
*/
Pager.prototype.drawPaginator = function() {// draws paginator
    // if returned data has no total page info default it to 0
    if (isNaN(this.totalPages) || this.totalPages <= 0)
        this.totalPages = 0;

    this.appendText(this.queryCount + ' ' + this.getPaginatorInfoText()); //paginatorInfoText is definied in JS_GlobalResources.js

    this.appendPagerButton('first', this.getPaginatorBtn('first')); // paginatorButtons is definied in JS_GlobalResources.js
    this.appendBlank();
    this.appendPagerButton('prev', this.getPaginatorBtn('prev')); // paginatorButtons is definied in JS_GlobalResources.js
    this.appendBlank();

    var startPage = this.currentPage - this.pageNumbersToDisplay / 2;
    if (startPage < 1) startPage += Math.abs(startPage);

    var endPage = startPage + this.pageNumbersToDisplay;
    if (endPage > this.totalPages) {
        endPage = this.totalPages + 1;
        startPage = endPage - this.pageNumbersToDisplay;
        startPage = startPage < 0 ? 0 : startPage;
    }

    for (var i = startPage; i < endPage; i++) {
        this.appendPagerButton(i);
        this.appendBlank();
    }
    this.appendPagerButton('next', this.getPaginatorBtn('next')); // paginatorButtons is definied in JS_GlobalResources.js        
    this.appendBlank();
    this.appendPagerButton('last', this.getPaginatorBtn('last')); // paginatorButtons is definied in JS_GlobalResources.js

    var pagerButtons = $(this.containerId).childElements();
    var currentPage = this.currentPage;
    var lastPage = this.totalPages;

    for (var i = 0; i < pagerButtons.size(); i++) {
        if (pagerButtons[i].id.include('page') && pagerButtons[i].id.split('_')[2] == currentPage) {
            pagerButtons[i].className = 'currentPage';
            pagerButtons[i].onclick = '';
        }
    }
    $(this.containerId + '_page_prev').value = this.currentPage - 1;
    $(this.containerId + '_page_next').value = this.currentPage + 1;

    if (currentPage == 0) {  // disable first & prev buttons
        $(this.containerId + '_page_first').className = 'disabledPager'
        $(this.containerId + '_page_first').onclick = '';

        $(this.containerId + '_page_prev').className = 'disabledPager'
        $(this.containerId + '_page_prev').onclick = '';
    }

    if (currentPage == lastPage) {  // disable first & prev buttons
        $(this.containerId + '_page_next').className = 'disabledPager'
        $(this.containerId + '_page_next').onclick = '';

        $(this.containerId + '_page_last').className = 'disabledPager'
        $(this.containerId + '_page_last').onclick = '';
    }
};

/**
Function to get culture specific paginator button text

@return culture specific paginator button text
*/
Pager.prototype.getPaginatorBtn = function(btnType) {
	return Resource.paginator[this.culture][btnType];
};

/**
Function to get culture specific paginator info text

@return culture specific paginator info text
*/
Pager.prototype.getPaginatorInfoText = function() {
    return Resource.paginatorInfoText[this.culture];
};

/**
Function to append info text (xyz records returned) to the pager
*/
Pager.prototype.appendText = function(infoText) {// adds text to the container
    var infoTextDiv = document.createElement('div');
    infoTextDiv.className = 'pagerInfoText';
    infoTextDiv.innerHTML = infoText;
    infoTextDiv.id = this.container.id + '_infoText';
    this.container.appendChild(infoTextDiv);
};

/**
Function to append pager button

@param buttonType Button type
@param buttonText Button text
*/
Pager.prototype.appendPagerButton = function(buttonType, buttonText) {// adds pager button to the container               
    var pager = document.createElement('a');

    if (buttonType == 'first') {
        pager.className = 'activePager';
        pager.value = 0;
        pager.innerHTML = ('<< ' + buttonText);
        pager.id = this.containerId + '_page_first';
    }
    else if (buttonType == 'last') {
        pager.className = 'activePager';
        pager.value = this.totalPages;
        pager.innerHTML = (buttonText + ' >>');
        pager.id = this.containerId + '_page_last';
    }
    else if (buttonType == 'prev') {
        pager.className = 'activePager';
        pager.value = 'page_prev';
        pager.innerHTML = ('< ' + buttonText);
        pager.id = this.containerId + '_page_prev';
    }
    else if (buttonType == 'next') {
        pager.className = 'activePager';
        pager.value = 'page_next';
        pager.innerHTML = (buttonText + ' >');
        pager.id = this.containerId + '_page_next';
    }
    else if (buttonType == 'next_set') {
        pager.className = 'activePager';
        pager.value = this.currentPage + this.pageNumbersToDisplay;
        pager.innerHTML = ' . . ';
        pager.id = this.containerId + '_page_next_set';
    }
    else if (!isNaN(buttonType)) {
        if (buttonType >= 0) {
            pager.className = 'activePager';
            pager.value = buttonType;
            pager.innerHTML = '&nbsp;' + (buttonType + 1) + '&nbsp;';
            pager.id = this.containerId + '_page_' + buttonType;
        }
    }
    var evt = this.eventName;

    function pubPagerClick() {        
        window.PageBus.publish(evt, { button: pager.value });
    }

    pager.onclick = pubPagerClick;
    this.container.appendChild(pager);
};

/**
Function to retrieve the next index

@param pagerValue
*/
Pager.prototype.getNextIndex = function(pagerValue) {
    var result = 0;
    if (pagerValue == 'last') {
        result = this.totalPages;
    } else if (pagerValue == 'prev') {
        result = this.currentPage - 1;
    } else if (pagerValue == 'next') {
        result = this.currentPage + 1;
    } else {
        try {
            result = parseInt(pagerValue);
        } catch (e) {
            result = 0;
        }
    }
    return result;
};

/**
Function to append a black space
*/
Pager.prototype.appendBlank = function() {// adds a blank space, spacer between paging buttons
    var blankSpace = document.createElement('span');
    blankSpace.id = '_blank';
    blankSpace.innerHTML = '&nbsp;';
    this.container.appendChild(blankSpace);
};


/**
Class to represent Result Group
@constructor
*/
function ResultGroup(basename, settings) {
    this.basename = basename;
    this.groupid = basename;
    this.gridid = basename + "-grid";
    this.paginatorid = basename + "-pager";
    this.pagerContainer = $(this.paginatorid);
    this.group = $(this.groupid);
    this.grid = $(this.gridid);
    this.defaultPageSize = 10;
    this.culture = "en-US"; //default
    this.rawData = null;
    this.culture = settings.culture;
    this.pagerEvent = settings.pagerEvent;
    this.filterEvent = settings.filterEvent;
    this.loadEvent = settings.loadEvent;
    this.query = Object.clone(settings.query);
    this.query.ReportTypeId = this.basename;
    this.store = Object.clone(settings.store);
    this.reportType = settings.reportType;
    this.resultType = settings.resultType;
    this.showTabs = [];
    this.showSpecialTabs = [];
    try {
    	var storedPageSize = this.store.getCookieValue(this.query.ResultTypeId + '.' + this.query.ReportTypeId);
    	$(basename + "-pagesizer").value = (storedPageSize > 0 ? storedPageSize : this.defaultPageSize);
    } catch (e) {
    	$(basename + "-pagesizer").value = this.defaultPageSize;
    }
    window.PageBus.subscribe(this.pagerEvent, this, this.pageData, null);
    window.PageBus.subscribe(this.filterEvent, this, this.getData, null);
    window.PageBus.subscribe(this.query.ReportTypeId, this, this.loadData, null);
    window.PageBus.subscribe('com.cec.report.drilldown.*', this, this.handleDrilldown, null);
};

/**
Function to handle drilldown reports
*/
ResultGroup.prototype.handleDrilldown = function(subj, msg, data) {
    var drillDownId = msg.id;
    var query = window.location.toString().split('?')[1];
    //TODO need to get drill downID label dynamicaly
    var idLabel = msg.reportIdLabel;
    if (msg.reportTypeId == Resource.reportType.RecipientCountry)		
        return window.location = 'ReportRecipientDrilldown.aspx?' + idLabel + '=' + drillDownId + '&' + Global.removeReportSpecificEntries(query);
    else
        return window.location = 'ReportDrilldown.aspx?' + idLabel + '=' + drillDownId + '&isDrilldown=true&' + Global.removeReportSpecificEntries(query) + '&reportTypeId=' + msg.reportTypeId;
};

/**
Function to set configuration values
*/
ResultGroup.prototype.config = function(settings) {
	this.culture = settings.culture;
	this.pagerEvent = settings.pagerEvent;
	this.filterEvent = settings.filterEvent;
	this.loadEvent = settings.loadEvent;
	this.query = Object.clone(settings.query);
	this.query.ReportTypeId = this.basename;
	this.query.ResultTypeId = settings.resultType;
	this.store = settings.store;
	this.reportType = settings.reportType;
	this.resultType = settings.resultType;
	this.query.SortColumn = this.store.getCookieValueByName(this.store.cookieSortCol, this.resultType + '.' + this.reportType);
	this.query.SortDirection = this.store.getCookieValueByName(this.store.cookieSortDir, this.resultType + '.' + this.reportType);
};

/**
Function to get report
*/
ResultGroup.prototype.getReport = function(query) {
	Global.showLoading();
	function onComplete(results) {
		var evt = query.ReportTypeId;
		window.PageBus.publish(evt, results);
	}	
	CEC.Web.Service.GetReport(query.Culture, query, onComplete, Global.onGetReportFail);
};

/**
Function to load data
*/
ResultGroup.prototype.loadData = function(subj, msg, data) {
    this.rawData = msg;
    msg.store = this.store;

    var formatter = new DataFormatter(msg); //once passed isDrilldown param    
    var _formatedData = formatter.getFormatedDataForSections(this.showTabs, this.showSpecialTabs);
    _formatedData.Years = msg.QueryParameters.Years;
    _formatedData.Units = Resource.measure[msg.QueryParameters.MeasureId];
    
    var adapter = new TableAdapter(this.culture, msg.QueryParameters.isDrilldown);
    adapter.dataFormatter = formatter;
    adapter.drawGrid(this.rawData, _formatedData, this.grid, this.getReport, this.query);

    //let MapManager handle the loading of formatted data
    window.PageBus.publish('com.cec.data.' + subj, _formatedData);

    // add paginator
    // pager has to be redraw - ex: to draw page #s from 5 to 14 when clicked 10
    var q = this.rawData.QueryParameters;
    this.pager = new Pager({
        culture: this.culture,
        container: this.paginatorid,
        pagesize: q.PageSize,
        pagenumber: q.PageNumber || 0,
        querycount: this.rawData.QueryCount,
        pagerEvent: this.pagerEvent,
        store: this.store,
        query: this.query
    });

    Global.hideLoading();
};

/**
Function to get data on changing media type
*/
ResultGroup.prototype.getData = function(subj, msg, data) {
	this.showTabs = msg.showTabs;
	this.showSpecialTabs = msg.showSpecialTabs;
	this.query.ResultTypeId = msg.query.ResultTypeId;
	this.query.Culture = this.culture;
	this.query.SortColumn = this.store.getCookieValueByName(this.store.cookieSortCol, this.query.ResultTypeId + '.' + this.query.ReportTypeId, "Name");
	this.query.SortDirection = this.store.getCookieValueByName(this.store.cookieSortDir, this.query.ResultTypeId + '.' + this.query.ReportTypeId, "0");
	this.query.PageNumber = this.store.getCookieValueByName(this.store.cookiePageNumber, this.query.ResultTypeId + '.' + this.query.ReportTypeId, "0");
	
	var media = this.store.getCookieValueByName(this.query.ResultTypeId + 'Media');
	
	var ungroupFacilityChkboxToggled = false;
	//check for NAICS checkbox toggling only for Facility Report
	if (this.query.ReportTypeId == Resource.reportType.Facility) ungroupFacilityChkboxToggled = !(this.query.UngroupFacilitiesOnIndustry == msg.query.UngroupFacilitiesOnIndustry);

	this.query.UngroupFacilitiesOnIndustry = msg.query.UngroupFacilitiesOnIndustry;
	this.query.PageSize = this.store.getCookieValue(this.query.ResultTypeId + '.' + this.query.ReportTypeId);
	if (isNaN(parseInt(this.query.PageSize, 10))) {
		this.query.PageSize = 10;
		this.store.setCookieValue(this.query.ResultTypeId + '.' + this.query.ReportTypeId, this.query.PageSize);
	}
	//use available raw data to toggle media types; otherwise request the server
	//FORCE to get NEW data when NAICS checkbox is toggled to get the data split / grouped by industry
	if (this.rawData != null && !ungroupFacilityChkboxToggled) this.loadData(subj, this.rawData, data);
	else this.getReport(this.query);
};

/**
Function get data on changing page size
*/
ResultGroup.prototype.pageData = function(subj, msg, data) {
    this.query.Culture = this.culture;
    this.query.PageNumber = this.pager.getNextIndex(msg.button);
    if (msg.pageSize) this.query.PageSize = msg.pageSize;
        
	this.store.setCookieValueByName(this.store.cookiePageNumber, this.query.ResultTypeId + '.' + this.query.ReportTypeId, this.query.PageNumber);
    this.getReport(this.query);
};


/**
Class to represent Table Adapter
@constructor
*/
function TableAdapter(culture, _isDrillDownReport) {
    this.culture = (culture && culture.length > 0) ? culture : "en-US";
    this.isDrillDownReport = _isDrillDownReport;

    //Determine if this has Naics Column only for Facility Reports (but not Drilldown Reports)
    this.data = '';
    this.sections = new Array(); // all media columns
};

/**
Function to draw grid

@param rawData Raw data received from the web request
@param formatedData Formated data of the raw data
@param gridContainer Container for the YUI data table
@param reportCallback Callback handler
@param query The query
*/
TableAdapter.prototype.drawGrid = function(_rawData, _formatedData, _gridContainer, _reportCallback, query) {
	this.rawData = _rawData;
	store = new Storage();

	var myDataSource = new YAHOO.util.DataSource(_formatedData.Records);
	myDataSource.responseSchema = {
		resultsList: 'Records',
		fields: _formatedData.HeaderNames
	};

	var myColumnDefs = _formatedData.Header;

	// attach sortedBy attributes only if sorted column being displayed
	var sortedBy = { key: 'Name', dir: 'asc' };
	if (this.columnExists(myColumnDefs, query.SortColumn)) {
		sortedBy = {
			key: query.SortColumn,
			dir: (query.SortDirection == Resource.querySortDirection.asc ? 'asc' : 'desc')
		};
	}

    var myDataTable;
    try {
	    myDataTable = new YAHOO.widget.DataTable(_gridContainer, myColumnDefs, myDataSource, { sortedBy: sortedBy });
	}
	catch(ex) { 
	    alert(ex.message);
    }

	// to  hightlight/unhighlight row on mouse over
	myDataTable.subscribe("rowMouseoverEvent", myDataTable.onEventHighlightRow);
	myDataTable.subscribe("rowMouseoutEvent", myDataTable.onEventUnhighlightRow);

	myDataTable.hideColumn("Id"); // this column(hidden) is used for making hyper links for column NAME

	var handleSorting = function(oColumn) {
		var sDir = oColumn.defaultDir; // 0 or 1 

		//Toggling if the Column is Clicked again
		if (oColumn.key == this.get("sortedBy").key) {
			sDir = (this.get("sortedBy").dir == 'yui-dt-asc') ? Resource.querySortDirection.desc : Resource.querySortDirection.asc;
		}
		query.SortDirection = sDir;
		query.SortColumn = oColumn.key;
		store.setCookieValueByName(store.cookieSortDir, query.ResultTypeId + '.' + query.ReportTypeId, query.SortDirection);
		store.setCookieValueByName(store.cookieSortCol, query.ResultTypeId + '.' + query.ReportTypeId, query.SortColumn);
		_reportCallback(query);
	};
	myDataTable.sortColumn = handleSorting;

	var nonMediaColumns = 0; //_formatedData.Header.size() - _formatedData.MediaColumns.size();
	_formatedData.Header.each(function(_h) {
		var c = _h.children;
		if (!c)
			nonMediaColumns += 1;   // to set colspan to Total cell in summary row
	});

	if (_formatedData.MediaColumns.size() > 0 && _rawData.QueryCount > 0) { // add footer sumary row only if a media is selected and has data in the grid
		var hasSpecialSection = this.rawData.SpecialSections.length > 0 ? true : false;

		var mediaValuesTotal = new Array();

		var records = _formatedData.Records;
		for (var i = 0; i < records.size(); i++) {
			tempSubRecords = '';
			for (var j = 0; j < _formatedData.MediaColumns.size(); j++) {
				var k = 0;

				var curSection = _formatedData.MediaColumns[j];
				if (i == 0) mediaValuesTotal[j] = 0;

				if ((curSection.include('Delta') && curSection.inspect().include('Delta')) || !curSection.include('Delta')) {
					val = this.dataFormatter.removeNonNumericValue(records[i][curSection]);
					val = (val == '--' ? 0 : val);

					if (isNaN(val)) val = eval(val.split(',').join(''));

					if (mediaValuesTotal[j] == undefined) mediaValuesTotal[j] = 0;
					mediaValuesTotal[j] += eval(val);
				}
			}
		}

		// Create the tfoot element, its row, and its cells
		var tbody = myDataTable.getTbodyEl();
		var tfoot = document.createElement('tfoot');
		var sumRow = tfoot.appendChild(document.createElement('tr'));
		// Add the cells and their content
		var th = document.createElement('th');
		// Assign the tfoot row a class for styling
		sumRow.className = 'summaryRow';
		th.setAttribute('class', 'totalForThisPageColumn');
		th.setAttribute('style', 'padding:4px 10px;');
		th.colSpan = nonMediaColumns;

		// display total for this not shown msg for Chemical Type grid as one pollutant may be long to more than one type, summation is not valid
		// summaryRowTitle is definied in JS_GlobalResources.js
		th.innerHTML = Resource.summaryRowTitle[query.ReportTypeId == Resource.reportType.ChemicalType ? 'chemicalType' : 'default'][this.culture];
		sumRow.appendChild(th);

		for (var i = 0; i < _formatedData.MediaColumns.size(); i++) {
			var curSection = _formatedData.MediaColumns[i];
			if (curSection.include('Rank') || curSection.include('Weight')) {// to add -- in summary row for either Air or Water media columns
				th = document.createElement('th');
				th.setAttribute('style', 'padding:4px 10px;');
				th.setAttribute('align', 'right');
				th.innerHTML = '--';
				sumRow.appendChild(th);
			}
			else {
				th = document.createElement('th');
				var rtPadding = navigator.appName.indexOf('Microsoft') >= 0 ? '&nbsp;&nbsp;' : '&nbsp;&nbsp;';
				th.setAttribute('style', 'padding:4px 2px;');
				th.setAttribute('align', 'right');
				th.innerHTML = query.ReportTypeId == Resource.reportType.ChemicalType ? '--' : this.dataFormatter.formatNumber(Math.round((mediaValuesTotal[i] > 0 ? mediaValuesTotal[i] : 0) * 100) / 100) + rtPadding;
				sumRow.appendChild(th);
			}
		}
		// Finally, insert the new tfoot before the table's tbody (order is important)
		tbody.parentNode.insertBefore(tfoot, tbody);
	}
};
/**
Function to find if the column 'columnToFind' exists in the list of columns data
*/
TableAdapter.prototype.columnExists = function(columns, columnToFind) {
	for (var i=0; i<columns.length; i++)
	{
		if (columns[i].children != undefined)
		{
			children = columns[i].children;
			for (var j=0; j<children.length; j++)
			{
				if (children[j].key == columnToFind) return true;			
			}
		}
		if (columns[i].key == columnToFind) return true;
	};
	return false;
};

/**
Class to represent Data Formatter
@constructor
*/
function DataFormatter(report) {
	this.rawData = report;
	this.dataFormatter = null;
	this.store = report.store;
	this.query = report.QueryParameters;
	if (this.store) this.pageSize = this.store.getCookieValue(this.query.ResultTypeId + '.' + this.query.ReportTypeId);
	if (isNaN(parseInt(this.pageSize))) this.pageSize = this.query.PageSize;
	this.pageNumber = this.query.PageNumber;
	this.queryCount = report.QueryCount;
	this.unitAbbr = Resource.measure[this.query.MeasureId];
	this.culture = (this.query.Culture && this.query.Culture.length > 0) ? this.query.Culture : "en-US";
	this.isDrillDownReport = this.query.IsDrilldown;
	this.data = '';
    this.sections = new Array(); // all media columns
    window.PageBus.subscribe('com.cec.tooltipAllMediaData', this, this.tooltipAllMediaData, {});
};

/**
Function to format Naics
*/
DataFormatter.prototype.naicsFormatter = function(Industries) {
    if (Industries) {
        var lines = Array();
        for (var i = 0; i < Industries.length; i++) {
            lines.push(Industries[i].Code + ' (' + Industries[i].Name + ')');
        }
        return lines.join('<br />');
    }
    return '';
};

/**
Function to load JSON object for selected sections(media) into this.data variable
*/
DataFormatter.prototype.loadSectionData = function() {
	var headers = this.getReportHeader();
	var records = this.getReportRecords();

	var tempHeader = '';
	var tempSubHeader = '';
	
	// this is used to assign value to datasource fields attribute
	var headerNames = ''; 
	var sectionHeaderNames = '';

	// stores media data for a facility of a state report
	var mediaData = new Array();
	// stores content for a facility of a state report
	var infoWindowMinimizedContent = new Array();

	var currentReportType = this.getReportType();
	var currentResultType = this.getResultType();

	var countryReportUrl = function(elCell, oRecord, oColumn, sData) {
		elCell.innerHTML = "<a href='javascript:;' onclick = 'window.PageBus.publish(\"com.cec.report.drilldown.Country\",{reportTypeId: \"Country\", reportIdLabel: \"countryId\", id: " + oRecord.getData("Id") + "});'>" + sData + "</a>";
	};

	var stateReportUrl = function(elCell, oRecord, oColumn, sData) {
		elCell.innerHTML = "<a href='javascript:;'  onclick='window.PageBus.publish(\"com.cec.report.drilldown.State\",{reportTypeId: \"State\", reportIdLabel: \"stateId\", id: " + oRecord.getData("Id") + "});'>" + sData + "</a>";
	};

	var industryReportUrl = function(elCell, oRecord, oColumn, sData) {
		elCell.innerHTML = "<a href='javascript:;'  onclick='window.PageBus.publish(\"com.cec.report.drilldown.Industry\",{reportTypeId: \"Industry\", reportIdLabel: \"industryId\", id: " + oRecord.getData("Id") + "});'>" + sData + "</a>";
	};

	var chemicalReportUrl = function(elCell, oRecord, oColumn, sData) {
		elCell.innerHTML = "<a href='javascript:;'  onclick='window.PageBus.publish(\"com.cec.report.drilldown.Chemical\",{reportTypeId: \"Chemical\", reportIdLabel: \"chemicalId\", id: " + oRecord.getData("Id") + "});'>" + sData + "</a>";
	};

	var facilityReportURL = function(elCell, oRecord, oColumn, sData) {
		elCell.innerHTML = "<a href='javascript:;'  onclick='window.PageBus.publish(\"com.cec.report.drilldown.Facility\",{reportTypeId: \"Facility\", reportIdLabel: \"facilityId\", id: " + oRecord.getData("Id") + "});'>" + sData + "</a>";
	};

	var recipientReportURL = function(elCell, oRecord, oColumn, sData) {
		elCell.innerHTML = "<a href='javascript:;'  onclick='window.PageBus.publish(\"com.cec.report.drilldown.Recipient\",{reportTypeId: \"Recipient\", reportIdLabel: \"recipientId\", id: " + oRecord.getData("Id") + "});'>" + sData + "</a>";
	};

	var recipientStateReportUrl = function(elCell, oRecord, oColumn, sData) {
		elCell.innerHTML = "<a href='javascript:;'  onclick='window.PageBus.publish(\"com.cec.report.drilldown.RecipientState\",{reportTypeId: \"RecipientState\", reportIdLabel: \"recipientStateId\", id: " + oRecord.getData("Id") + "});'>" + sData + "</a>";
	};

	if (currentReportType == Resource.reportType.Facility) {
		if ($('industrySpan0')) $('industrySpan0').removeClassName('hidden');
		if ($('industrySpan1')) $('industrySpan1').removeClassName('hidden');
		stateReportUrl = function(elCell, oRecord, oColumn, sData) {
			elCell.innerHTML = "<a href='javascript:;'  onclick='window.PageBus.publish(\"com.cec.report.drilldown.State\",{reportTypeId: \"State\", reportIdLabel: \"stateId\", id: " + oRecord.getData("StateId") + "});'>" + sData + "</a>";
		};

		countryReportUrl = function(elCell, oRecord, oColumn, sData) {
			elCell.innerHTML = "<a href='javascript:;'  onclick='window.PageBus.publish(\"com.cec.report.drilldown.Country\",{reportTypeId: \"Country\", reportIdLabel: \"countryId\", id: " + oRecord.getData("CountryId") + "});'>" + sData + "</a>";
		};

		tempHeader = '{"key":"Num","label":"#",sortable:false},' +
                '{"defaultDir":"0", "key":"Name","label":"' + headers[0] + '",sortable:true,resizeable:false' + (this.isDrillDownReport == true ? '' : ', formatter:' + facilityReportURL) + '},' +
                '{"defaultDir":"0", "key":"PrTrId","label":"' + headers[1] + '",sortable:true,resizeable:false' + (this.isDrillDownReport == true ? '' : ', formatter:' + facilityReportURL) + '},' +
                '{"defaultDir":"0", "key":"City","label":"' + headers[2] + '",sortable:true,resizeable:false},' +
                '{"defaultDir":"0", "key":"State","label":"' + headers[3] + '",sortable:true,resizeable:false' + (this.isDrillDownReport == true ? '' : ', formatter:' + stateReportUrl) + '},' +
                '{"defaultDir":"0", "key":"Country","label":"' + headers[4] + '",sortable:true,resizeable:false' + ((this.isDrillDownReport == true) ? '' : ', formatter:' + countryReportUrl) + '}';
		if (this.specialSections.inspect().include('Naics')) {
			tempHeader += ',{"defaultDir":"0", "key":"NaicsCode","label":"' + headers[5] + '",sortable:true,resizeable:false}';
			tempHeader += ',{"defaultDir":"0", "key":"Industry","label":"' + headers[6] + '",sortable:true,resizeable:false}';
		}
	}
	else if (currentReportType == Resource.reportType.Industry) {
		tempHeader = '{"key":"Num","label":"#",sortable:false},' +
                '{"defaultDir":"0", "key":"Name","label":"' + headers[0] + '",sortable:true,resizeable:false' + (this.isDrillDownReport == true ? '' : ', formatter:' + industryReportUrl) + '},' +
                '{"defaultDir":"0", "key":"NaicsCode","label":"' + headers[1] + '",sortable:true,resizeable:false' + (this.isDrillDownReport == true ? '' : ', formatter:' + industryReportUrl) + '}';
	}
	else if (currentReportType == Resource.reportType.Country) {
		tempHeader = '{"key":"Num","label":"#",sortable:false},' +
                    '{"defaultDir":"0", "key":"Name","label":"' + headers[0] + '",sortable:true,resizeable:false' + (this.isDrillDownReport == true ? '' : ', formatter:' + countryReportUrl) + '}';
	}
	else if (currentReportType == Resource.reportType.RecipientCountry) {
		countryReportUrl = function(elCell, oRecord, oColumn, sData) {
			elCell.innerHTML = "<a href='javascript:;'  onclick='window.PageBus.publish(\"com.cec.report.drilldown.Country\",{reportTypeId: \"RecipientCountry\", reportIdLabel: \"destination\", id: " + oRecord.getData("Id") + "});'>" + sData + "</a>";
		};
		tempHeader = '{"key":"Num","label":"#",sortable:false},' +
                '{"defaultDir":"0", "key":"Name","label":"' + headers[0] + '",sortable:true,resizeable:false' + (this.isDrillDownReport == true ? '' : ', formatter:' + countryReportUrl) + '}';
	}
	else if (currentReportType == Resource.reportType.State) {
		countryReportUrl = function(elCell, oRecord, oColumn, sData) {
			elCell.innerHTML = "<a href='javascript:;'  onclick='window.PageBus.publish(\"com.cec.report.drilldown.Country\",{reportTypeId: \"Country\", reportIdLabel: \"countryId\", id: " + oRecord.getData("CountryId") + "});'>" + sData + "</a>";
		};
		tempHeader = '{"key":"Num","label":"#",sortable:false},' +
                '{"defaultDir":"0", "key":"Name","label":"' + headers[0] + '",sortable:true,resizeable:false' + (this.isDrillDownReport == true ? '' : ', formatter:' + stateReportUrl) + '},' +
                '{"defaultDir":"0", "key":"Country","label":"' + headers[1] + '",sortable:true,resizeable:false' + (this.isDrillDownReport == true ? '' : ', formatter:' + countryReportUrl) + '}';
	}
	else if (currentReportType == Resource.reportType.Chemical) {
		tempHeader = '{"key":"Num","label":"#",sortable:false},' +
                '{"key":"Id","label":"Id"},' +
                '{"defaultDir":"0", "key":"Name","label":"' + headers[0] + '",sortable:true, resizeable:false' + (this.isDrillDownReport == true ? '' : ', formatter:' + chemicalReportUrl) + '},' +
                '{"defaultDir":"0", "key":"CasNumber","label":"' + headers[1] + '",sortable:true, resizeable:false' + (this.isDrillDownReport == true ? '' : ', formatter:' + chemicalReportUrl) + '}';
	}
	else if (currentReportType == Resource.reportType.ChemicalType) {
		tempHeader = '{"key":"Num","label":"#",sortable:false},' +
                '{"key":"Id","label":"Id"},' +
                '{"defaultDir":"0", "key":"Name","label":"' + headers[0] + '",sortable:true, resizeable:false}';
	}
	else if (currentReportType == Resource.reportType.Recipient) {
		recipientStateReportUrl = function(elCell, oRecord, oColumn, sData) {
			elCell.innerHTML = "<a href='javascript:;'  onclick='window.PageBus.publish(\"com.cec.report.drilldown.RecipientState\",{reportTypeId: \"RecipientState\", reportIdLabel: \"recipientStateId\", id: " + oRecord.getData("StateId") + "});'>" + sData + "</a>";
		};
		countryReportUrl = function(elCell, oRecord, oColumn, sData) {
			elCell.innerHTML = "<a href='javascript:;'  onclick='window.PageBus.publish(\"com.cec.report.drilldown.Country\",{reportTypeId: \"Country\", reportIdLabel: \"countryId\", id: " + oRecord.getData("CountryId") + "});'>" + sData + "</a>";
		};

		tempHeader = '{"key":"Num","label":"#",sortable:false},' +
                '{"defaultDir":"0", "key":"Name","label":"' + headers[0] + '",sortable:true,resizeable:false' + (this.isDrillDownReport == true ? '' : ', formatter:' + recipientReportURL) + '},' +
                '{"defaultDir":"0", "key":"City","label":"' + headers[1] + '",sortable:true,resizeable:false},' +
                '{"defaultDir":"0", "key":"State","label":"' + headers[2] + '",sortable:true,resizeable:false' + (this.isDrillDownReport == true ? '' : ', formatter:' + recipientStateReportUrl) + '},' +
                '{"defaultDir":"0", "key":"Country","label":"' + headers[3] + '",sortable:true,resizeable:false}';
	}
	else if (currentReportType == Resource.reportType.RecipientState) {
		tempHeader = '{"key":"Num","label":"#",sortable:false},' +
                '{"defaultDir":"0", "key":"Name","label":"' + headers[0] + '",sortable:true,resizeable:false' + (this.isDrillDownReport == true ? '' : ', formatter:' + recipientStateReportUrl) + '},' +
                '{"defaultDir":"0", "key":"Country","label":"' + headers[1] + '",sortable:true,resizeable:false}';
	}

	// possible header keys, required for YUI datatable to make cell clickable
	headerNames = '"Latitude", "Longitude", "chemName", "Num", "Id", "PrTrId", "NaicsCode", "CasNumber", "Name", "City", "State", "Country", "StateId", "CountryId", "Industry"';
	var specialSectionHeader = '';
	var specialSectionHeaderNames = '';

	// format header begins here
	var maxsections = this.rawData.Sections.length;
	for (var i = 0; i < this.getSections().size(); i++) {
		var sec = this.getSection(i);
		if (!sec) continue; //not to add sections which are hidden :)

		var j = null;
		for (var x = 0; x < maxsections; x++) {
			var rawSectionid = this.rawData.Sections[x].Id;
			if (sec == rawSectionid) {
				j = x;
				break;
			}
		}
		if (j == null) continue;

		var showSection = j;    // adds media type to table in google map bubble window
		var sectionHeaders = this.getSectionHeader(showSection);
		var sectionSubHeaders = this.getSectionSubHeaders(showSection);
		var sectionRecords = this.getSectionRecords(showSection);

		tempSubHeader += '{"label":"' + sectionHeaders + '","children": [';
		for (var k = 0; k < sectionSubHeaders.length; k++) {
			if ((sectionSubHeaders[k].include('Delta') && this.specialSections.inspect().include('Delta')) || !sectionSubHeaders[k].include('Delta')) {
				var sortable = (sectionSubHeaders[k].include('Delta') ? false : true);
				var mySortDir = '"defaultDir":"1"';
				tempSubHeader += '{"key":"' + this.removeSpecialChars(sectionSubHeaders[k]) + '_' + this.rawData.Sections[showSection].Id +
                        '", "label":"' + sectionSubHeaders[k] + (sectionSubHeaders[k].include('%') ? '' : ' (' + this.unitAbbr + ')') +
                        '",sortable:' + sortable + ',' + mySortDir + ', resizeable:false},';
				sectionHeaderNames += '"' + this.removeSpecialChars(sectionSubHeaders[k]) + '_' + this.rawData.Sections[showSection].Id + '",';  // just header names, list of all headers has to be assigned to YUI table
			}
		}

		// format special section header begins here
		if (currentReportType == Resource.reportType.Chemical && this.specialSections.inspect().include('TEP')) {
			var curSection = this.rawData.Sections[showSection].Id;
			var specialSections, specialSectionHeader;
			if (curSection.include('Air')) {
				specialSections = this.getSpecialSections();
				specialSectionHeader = '';
				for (var k = 0; k < specialSections.size(); k++) {
					var ss = specialSections[k];
					specialSectionHeader = ss.Id;
					specialSectionHeaderLabel = ss.SectionHeader;
					specialSectionSubHeaders = ss.SubHeaders;
					if (specialSectionHeader.include('Air')) {

						// special section with sub headers, add sub headers as children
						if (specialSectionSubHeaders.size() > 0) {
							tempSubHeader += '{"label":"' + specialSectionHeaderLabel + '","children": [';

							for (var l = 0; l < specialSectionSubHeaders.size(); l++) {
								tempSubHeader += '{"key":"' + this.removeSpecialChars(specialSectionSubHeaders[l]) + '_' + this.removeSpecialChars(specialSectionHeader) + '", "label":"' + specialSectionSubHeaders[l] + '","sortable":"true", "defaultDir":"1", "resizeable":"false"},';
								sectionHeaderNames += '"' + this.removeSpecialChars(specialSectionSubHeaders[l]) + '_' + this.removeSpecialChars(specialSectionHeader) + '",';  // just header names, list of all headers has to be assigned to YUI table
							}
							tempSubHeader = tempSubHeader.substr(0, tempSubHeader.length - 1);
						}
						else {  // special section without sub headers
							tempSubHeader += '{"key":"' + this.removeSpecialChars(specialSectionHeader) + '", "label":"' + specialSectionHeaderLabel + '","sortable":"true","defaultDir":"1", "resizeable":"false"},';
							sectionHeaderNames += '"' + this.removeSpecialChars(specialSectionHeader) + '",';  // just header names, list of all headers has to be assigned to YUI table
						}

						if (specialSectionSubHeaders.size() > 0)
							tempSubHeader += ']},';
					}
				}
			}

			if (curSection.include('Water')) {
				specialSections = this.getSpecialSections();
				specialSectionHeader = '';
				for (var k = 0; k < specialSections.size(); k++) {
					var ss = specialSections[k];
					specialSectionHeader = ss.Id;
					specialSectionHeaderLabel = ss.SectionHeader;
					specialSectionSubHeaders = ss.SubHeaders;
					if (specialSectionHeader.include('Water')) {

						// special section with sub headers, add sub headers as children
						if (specialSectionSubHeaders.size() > 0) {
							tempSubHeader += '{"label":"' + specialSectionHeaderLabel + '","children": [';

							for (var l = 0; l < specialSectionSubHeaders.size(); l++) {
								tempSubHeader += '{"defaultDir":"1", "key":"' + this.removeSpecialChars(specialSectionSubHeaders[l]) + '_' + this.removeSpecialChars(specialSectionHeader) + '", "label":"' + specialSectionSubHeaders[l] + '","sortable":"true", "resizeable":"false"},';
								sectionHeaderNames += '"' + this.removeSpecialChars(specialSectionSubHeaders[l]) + '_' + this.removeSpecialChars(specialSectionHeader) + '",';  // just header names, list of all headers has to be assigned to YUI table
							}
							tempSubHeader = tempSubHeader.substr(0, tempSubHeader.length - 1);
						}
						else {  // special section without sub headers
							tempSubHeader += '{"defaultDir":"1", "key":"' + this.removeSpecialChars(specialSectionHeader) + '", "label":"' + specialSectionHeaderLabel + '","sortable":"true", "resizeable":"false"},';
							sectionHeaderNames += '"' + this.removeSpecialChars(specialSectionHeader) + '",';  // just header names, list of all headers has to be assigned to YUI table
						}

						if (specialSectionSubHeaders.size() > 0)
							tempSubHeader += ']},';
					}
				}
			}
		} // format special section header ends here
		tempSubHeader = tempSubHeader.substr(0, tempSubHeader.length - 1);
		tempSubHeader += ']}, ';
	} // format header ends here

	if (sectionHeaderNames.length > 0) {
		sectionHeaderNames = sectionHeaderNames.substr(0, sectionHeaderNames.length - 1);
		tempSubHeader = tempSubHeader.substr(0, tempSubHeader.length - 2);
		tempHeader += ', ' + tempSubHeader;
	}

	var tempData = '';
	var tempSubRecords = '';
	var id;
	var states = "";

	// format data begins here
	for (var i = 0; i < records.size(); i++) {

		tempSubRecords = '';
		for (var j = 0; j < this.rawData.Sections.size(); j++) {
			var curSection = this.rawData.Sections[j].Id;
			curSection = curSection == null ? '' : curSection;

			if (curSection == '') continue;

			var addMediaToGrid = false; // addMediaToGrid adds media type to the grid
			if (this.rawData.Sections[j].Id == curSection) addMediaToGrid = true;

			showSection = j;
			var sectionSubHeaders = this.getSectionSubHeaders(showSection);
			var sectionRecords = this.getSectionRecords(showSection);
			var k = 0;
			// append media values
			for (var l = 0; l < sectionSubHeaders.size(); l++) {
				if (addMediaToGrid && (sectionSubHeaders[l].include('Delta') && this.specialSections.inspect().include('Delta')) || !sectionSubHeaders[l].include('Delta')) {
					tempSubRecords += '"' + this.removeSpecialChars(sectionSubHeaders[l]) + '_' + this.rawData.Sections[showSection].Id + '":"' + this.removeNonNumericValue(sectionRecords[i][k]) + '",';
				}
				k++;
			}

			// append special section data begins here
			if (currentReportType == Resource.reportType.Chemical && this.specialSections.inspect().include('TEP')) {
				var curSection = this.rawData.Sections[showSection].Id;
				if (curSection.include('Air')) {
					if (addMediaToGrid) tempSubRecords += this.getSpecialSectionData('Air', i);
				}
				if (curSection.include('Water')) {
					if (addMediaToGrid) tempSubRecords += this.getSpecialSectionData('Water', i);
				}
			} // append special section data ends here
		}

		tempSubRecords = tempSubRecords.substr(0, tempSubRecords.length - 1);

		if (currentReportType == Resource.reportType.Facility) {
			var allMediaTypeData = '&nbsp;<span onclick=\'return false;\' class=\'toolTipText\' onmouseover=\\\"window.PageBus.publish(\'com.cec.tooltipAllMediaData\', { index: ' + i + ' })\\\" onmouseout=\'UnTip()\'><img src=\'includes/img/icon_table.png\' border=0 height=10 /></span>';

			tempData += ' { "Num":' + ((this.pageNumber * this.pageSize) + (i + 1)) + ',' +
                    '"Id":' + records[i].Id + ',' +
                    '"Latitude":"' + records[i].Latitude + '",' +
                    '"Longitude":"' + records[i].Longitude + '",' +
                    '"PrTrId":"' + records[i].PrTrId + '",' +
                    '"Name":"' + records[i].Name + allMediaTypeData + '",' +
                    '"City":"' + records[i].City + '",' +
                    '"State":"' + records[i].State + '",' +
                    '"StateId":"' + records[i].StateId + '",' +
                    '"Country":"' + records[i].Country + '",' +
                    '"CountryId":"' + records[i].CountryId + '",' +
                    '"NaicsCode":"' + records[i].NaicsCode + '",' +
                    '"Industry":"' + records[i].Industry + '"';
		}
		else if (currentReportType == Resource.reportType.Industry) {
			tempData += ' { "Num":' + ((this.pageNumber * this.pageSize) + (i + 1)) + ',' +
                    '"Id":' + records[i].Id + ',' +
                    '"NaicsCode":' + records[i].NaicsCode + ',' +
                    '"Name":"' + records[i].Name + '"';
		}
		else if (currentReportType == Resource.reportType.Country || currentReportType == Resource.reportType.RecipientCountry) {
			tempData += ' { "Num":' + ((this.pageNumber * this.pageSize) + (i + 1)) + ',' +
                    '"Id":' + records[i].Id + ',' +
                    '"Name":"' + records[i].Name + '"';
		}
		else if (currentReportType == Resource.reportType.State) {
			id = ((this.pageNumber * this.pageSize) + (i + 1));

			tempData += ' { "Num":' + ((this.pageNumber * this.pageSize) + (i + 1)) + ',' +
                    '"Id":' + records[i].Id + ',' +
                    '"Latitude":"' + records[i].Latitude + '",' +
                    '"Longitude":"' + records[i].Longitude + '",' +
                    '"Name":"' + records[i].Name + '",' +
                    '"Country":"' + records[i].Country + '",' +
                    '"CountryId":"' + records[i].CountryId + '"';
		}
		else if (currentReportType == Resource.reportType.Chemical) {
			var blankSpace = '&nbsp;'
			var abbreviations = Global.getColorCodedAbbreviation(this.culture, records[i].IsCAC, records[i].IsCarcinogen, records[i].IsCepaToxic, records[i].IsGHG, records[i].IsMetal, records[i].IsPBT, records[i].IsProp65);

			tempData += ' { "Num":' + ((this.pageNumber * this.pageSize) + (i + 1)) + ',' +
                    '"Id":' + records[i].Id + ',' +
                    '"CasNumber":"' + (records[i].CasNumber == null ? '--' : records[i].CasNumber) + '",' +
                    '"chemName":"' + records[i].Name + '",' +
                    '"Name":"' + records[i].Name + (abbreviations.length > 0 ? blankSpace : '') + abbreviations + '"';
		}
		else if (currentReportType == Resource.reportType.Recipient) {
			id = ((this.pageNumber * this.pageSize) + (i + 1));
			tempData += ' { "Num":' + id + ',' +
                    '"Id":' + records[i].Id + ',' +
                    '"Latitude":"' + records[i].Latitude + '",' +
                    '"Longitude":"' + records[i].Longitude + '",' +
                    '"Name":"' + records[i].Name + '",' +
                    '"Address":"' + records[i].Address + '",' +
                    '"City":"' + records[i].City + '",' +
                    '"State":"' + records[i].State + '",' +
                    '"StateId":"' + records[i].StateId + '",' +
                    '"Country":"' + records[i].Country + '",' +
                    '"CountryId":"' + records[i].CountryId + '"';
		}
		else if (currentReportType == Resource.reportType.ChemicalType) {
			tempData += ' { "Num":' + ((this.pageNumber * this.pageSize) + (i + 1)) + ',' +
                    '"Id":' + records[i].Id + ',' +
                    '"Name":"' + records[i].Name + '"';
		}
		else if (currentReportType == Resource.reportType.RecipientState) {
			id = ((this.pageNumber * this.pageSize) + (i + 1));

			tempData += ' { "Num":' + ((this.pageNumber * this.pageSize) + (i + 1)) + ',' +
                    '"Id":' + records[i].Id + ',' +
                    '"Latitude":"' + records[i].Latitude + '",' +
                    '"Longitude":"' + records[i].Longitude + '",' +
                    '"Name":"' + records[i].Name + '",' +
                    '"Country":"' + records[i].Country + '",' +
                    '"CountryId":"' + records[i].CountryId + '"';
		}

		if (tempSubRecords.length > 0) tempData += ',' + tempSubRecords;

		tempData += '}, ';
	} // format data ends here
	tempData = tempData.substr(0, tempData.length - 2); // remove extra comma and a space (, )

	// remove extra comma and a space (, )
	if (states.length > 0) states = states.substr(0, states.length - 2);

	// format a JSON object
	tempData = '{ "RecordsReturned":' + this.pageSize + ', "QueryCount":' + this.queryCount + ', "StartIndex":' + ((this.pageNumber * this.pageSize) + 1) + ', "EndIndex":' + ((this.pageNumber * this.pageSize) + i) + ', "sort":"null", "dir":"asc", ' +
            '"HeaderNames": [' + headerNames + ',' + sectionHeaderNames + '], ' +
            '"NonMediaColumns": [' + headerNames + '],' +  // for generating summary row
            '"MediaColumns": [' + sectionHeaderNames + '],' +  // for generating summary row
            '"Header": [' + tempHeader + '], ' +
            '"hasDelta": ' + (tempData.indexOf('_%_', 0) > 0) + ', ' +
            '"Records": [' + tempData + '] }';

	//jQuery('#debug').text(tempData);
	this.data = tempData.evalJSON();
};

/**
Function to get tooltip
*/
//DataFormatter.prototype.getToolTip = function(type) {
//    return toolTips[this.culture][type];
//};

/**
Function to get section data
*/
DataFormatter.prototype.getSection = function(index) {    
    return this.sections[index];
};

/**
Function to get selected sections
*/
DataFormatter.prototype.getSections = function() {
    return this.sections;
};

/**
Function to get page number
*/
DataFormatter.prototype.getPageNumber = function() {    
    return this.pageNumber;
};

/**
Function to get report headers
*/
DataFormatter.prototype.getReportHeader = function() {
    return this.rawData.ReportHeaders;
};

/**
Function to get report records
*/
DataFormatter.prototype.getReportRecords = function() {
    return this.rawData.ReportRecords;
};

/**
Function to get report type
*/
DataFormatter.prototype.getReportType = function() {
    return this.query.ReportTypeId;
};

/**
Function to get result type
*/
DataFormatter.prototype.getResultType = function() {
    return this.query.ResultTypeId;
};

/**
Function to get formated JSON obj suitable for YUI Datatabe for selected sections
*/
DataFormatter.prototype.getFormatedDataForSections = function(sections, specialSections) {        
    this.sections = sections;
    this.specialSections = specialSections;
    this.loadSectionData();
    if (this.query.ReportTypeId == 'Facility') this.loadMapTables();
    return this.data;
};

/**
Function to get raw data
*/
DataFormatter.prototype.getRawData = function() {
    return this.rawData;
};

/**
Function to get selected section's header
*/
DataFormatter.prototype.getSectionHeader = function(section) {
    return this.getRawData().Sections[section].SectionHeader;
};

/**
Function to get selected section sub header
*/
DataFormatter.prototype.getSectionSubHeaders = function(section) {
    return this.getRawData().Sections[section].SubHeaders;
};

/**
Function to get selected section records
*/
DataFormatter.prototype.getSectionRecords = function(section) {
    return this.getRawData().Sections[section].Records;
};

/**
Function to get special sections
*/
DataFormatter.prototype.getSpecialSections = function() {   
    return this.getRawData().SpecialSections;
};

/**
Function to get selected special section data
*/
DataFormatter.prototype.getSpecialSectionData = function(section, index) {
    var specialSections = this.getSpecialSections();
    var spSecHeader = '', spSecSubHeaders = '', spSecRecords = '', retData = '', spSecHeaderLabel = '';

    for (var i = 0; i < specialSections.size(); i++) {
        spSecHeader = specialSections[i].Id;
        spSecHeaderLabel = specialSections[i].SectionHeader;
        if (spSecHeader.include(section)) {

            spSecSubHeaders = specialSections[i].SubHeaders;
            spSecRecords = specialSections[i].Records[index];

            if (spSecSubHeaders.size() > 0) {
                for (var j = 0; j < spSecSubHeaders.size(); j++)
                    retData += '"' + spSecSubHeaders[j] + "_" + this.removeSpecialChars(spSecHeader) + '":"' + this.removeNonNumericValue(spSecRecords[j]) + '",';
            }
            else {
                retData += '"' + this.removeSpecialChars(spSecHeader) + '":"' + this.removeNonNumericValue(spSecRecords) + '",';
            }
        }
    }
    return retData;
};

/**
Function to remove comma in the numbers for charting
*/
DataFormatter.prototype.removeCommas = function(value) {
	value = value + '';
	return (value.include(',') ? (value.split(',')).join('') : value);
};

/**
Function to replaces any non numeric value with '--'
*/
DataFormatter.prototype.removeNonNumericValue = function(value) {
	var temp = this.removeCommas(value);

	if (temp == 'Infinity' || temp == null || temp == '' || temp == undefined || isNaN(temp))
		return '--';
	else
		return value;
};

/**
Function to remove special characters to avoid conflict in creating JSON Object
*/
DataFormatter.prototype.removeSpecialChars = function(input) {
	return (((($w(input).join('_')).split('.')).join('')).split('/')).join('_');
};

/**
Function to load formated data for a section

@param section Section to get the formated data
*/
DataFormatter.prototype.loadFormatedDataForSection = function(_section) {// is used by Charts (ChartManager.js)
    var reqSections;

    if (_section.include(','))
        reqSections = _section.split(',');
    else {
        reqSections = new Array();
        reqSections[0] = _section;
    }

    var headerNames = ''; // this is used to assign value to datasource fields attribute
    headerNames = 'category:"Name",data:[';
    var sections;

    //If the Chart Type or Media is CarcinogenAirScore or CarcinogenWaterScore or ToxinAirScore or ToxinWaterScore
    //This may not accomodate Subsections whose media name does'nt Include Score like ToxinAirRank	
    if (_section.include('Score')) sections = this.getSpecialSections();
    else sections = this.rawData.Sections;

    for (var i = 0; i < sections.size(); i++) {
        for (var k = 0; k < reqSections.size(); k++) {
            if (sections[i].Id == reqSections[k]) {
                headerNames += '"' + sections[i].Id + '",';
            }
        }
    }

    if (headerNames.length > 0) headerNames = headerNames.substring(0, headerNames.length - 1);

    headerNames += ']';

    // format data
    var data = '';
    var records = this.getReportRecords();

    for (var j = 0; j < records.size(); j++) {
        var NaicsOrCas = records[j].NaicsCode;
        if (NaicsOrCas == null) //It means the report is Chemical 
            NaicsOrCas = records[j].CasNumber;

        if (NaicsOrCas == null) //Some Chemicals Does'nt Have CAS Number
            NaicsOrCas = '--';



        data += '{Name:"' + records[j].Name + ' (' + NaicsOrCas + ') ' + '",';

        for (var i = 0; i < sections.size(); i++) {
            var sectionRecords;
            for (var k = 0; k < reqSections.size(); k++) {

                if (sections[i].Id == reqSections[k]) {
                    sectionRecords = sections[i].Records;

                    var _tempVal = this.removeNonNumericValue(this.removeCommas(sectionRecords[j]));
                    data += '' + reqSections[k] + ':"' + (_tempVal == '--' ? 0 : _tempVal) + '",';
                    //To be used for the Legend in Pie Chart
                    data += '' + 'nameandmedia' + ':"' + records[j].Name + ' (' + NaicsOrCas + ')' + ': ' + (_tempVal == '--' ? 0 : sectionRecords[j]) + ' ' + this.unitAbbr + '",';
                    data += '' + 'unit' + ':"' + this.unitAbbr + '",';
                }
            }
        }

        // trim the last char (,)
        if (data.length > 0) data = data.substring(0, data.length - 1);

        data += '},';
    }

    // trim the last char (,)
    if (data.length > 0) data = data.substring(0, data.length - 1);

    // make the JSON object
    var tempData = '{' +
            '"HeaderNames": {' + headerNames + '},' +
            '"Records":[' + data + ']}';

    this.data = tempData.evalJSON();
};

/**
Function to tooltip all media data in tabular form
*/
DataFormatter.prototype.tooltipAllMediaData = function(subj, results, data) {
    Tip(this.data.MapTables[results.index].table);
};
/** */
//DataFormatter.prototype.rawData = null;

/**
Function to populate map tables
*/
DataFormatter.prototype.loadMapTables = function() {
    var tables = [];
    for (var i = 0; i < this.rawData.ReportRecords.length; i++) {
        var _id = this.rawData.ReportRecords[i].Id;

        var content = '<table id="mediaDataTable" width=100% border=0 cellspacing=1 cellpadding=2><tr><th align=center>' + Resource.mediaType[this.culture] + '</th>';

        var headers = this.rawData.Sections[0].SubHeaders;
        for (var h = 0; h < headers.length; h++) {
            content += '<th align=center>' + headers[h] + '</th>';
        }
        content += '</tr>';

        var sections = this.rawData.Sections;
        for (var s = 0; s < sections.length; s++) {
            var section = sections[s];
            content += '<tr><td style="text-align:left;">' + section.SectionHeader + '</td>';

            var records = section.Records[i];
            for (var r = 0; r < records.length; r++) {
                content += '<td class=alignRight>' + this.removeNonNumericValue(records[r]) + '</td>';
            }
            content += '</tr>';
        }

        content += '</table>';
        var t = { id: _id, table: content };
        tables.push(t);
    }
    this.data.MapTables = tables;
};

/**
Function to load media data
*/
DataFormatter.prototype.loadMediaData = function() {
    var sections = this.rawData.Sections;
    var media = [];
    var keys = this.rawData.QueryParameters.Years;
    if (this.data.hasDelta) {
        keys.push("&delta;");
        keys.push("&delta;_%");
    }

    for (var i = 0; i < sections.length; i++) {
        var medium = {};
        var section = sections[i];
        medium.id = section.Id;
        medium.label = section.SectionHeader;
        medium.keys = [];
        for (var j = 0; j < keys.length; j++) {
            var key = keys[j] + '_' + section.Id;
            medium.keys.push(key);
        }
        media.push(medium);
    }
    this.data.AllMedia = media;
};

/**
Function to get input in this format <code>(###,####.XY)</code>

@param num The number to be formated
@return Returns the formated number
*/
DataFormatter.prototype.formatNumber = function(_num) {
    _num += '';
    x = _num.split('.');
    x1 = x[0];
    try {
        x2 = x[1];
        switch (x2.length) {
            case 0:
                x2 = '00';
                break;
            case 1:
                x2 = x2 + '0';
                break;
        }

    } catch (e) { x2 = '00' };

    var rgx = /(\d+)(\d{3})/;
    while (rgx.test(x1)) {
        x1 = x1.replace(rgx, '$1' + ',' + '$2');
    }
    return x1 + "." + x2;
};
