 /**********************************************
@title:  reportingService.js
@author:  Andrew Southwick
@date:    02-11-2007
@rev:     1.2
@desc:    Reporting Service - this is the principle JS Controller framework file for reporting and references on all
* other <view type>Manager.js files for runtime (the core view managers and have been seperated into other js files.
@assumes: prototype.js 1.5 rel.
@assumes: commonManager.js,<list others here>
********************************/
 

var ReportingService = Class.create();

ReportingService.prototype = {
    isActive: true,
    initialize:function() {
		//initialize properties here
	},
	api:{},
	model:{
		reportRegistry:[],
		reportsWaiting:[],
		reportsToClean:[],
		reportParameterRegistry:[],
		reportParameterMap:{},
		isPersonalizationDataReady:false,
		isDomReady:false
	},
	controller: {
		init:{},
		reportingManager:{},
		viewManagers:{
			commonViewManager:{},
			framesetViewManager:{},
			errorPageViewManager:{},
			categorySearchViewManager:{},
			categoryViewManager:{},
			siteSearchViewManager:{},
			productLoaderViewManager:{},
			productpageViewManager:{},
			productImageLoaderViewManager:{},
			viewLargerViewManager:{},
			altViewsViewManager:{},
			zoomViewViewManager:{},
			quicklookViewManager:{},
			outfitViewManager:{},
			inlineBagAddViewManager:{},
			shoppingBagViewManager:{},
			firstCheckoutPageViewManager:{},
			checkoutOrderModuleViewManager:{},
			orderConfirmViewManager:{},
			internationalPlaceOrderViewManager:{},
			reviewsWrapperViewManager:{},
			reviewsProfileViewManager:{},
			reviewsVoteViewManager:{},
			swatchEnagementViewManager:{},
			categoryFacetedSearchViewManager:{}
		},
		appManagers:{
			shopBySizeAppManager:{},
			facetedSearchAppManager:{},
			searchAppManager:{},
			checkoutAppManager:{}
		},
		AbstractReportViewManager:null,
		AbstractReportAppManager:null,
		AbstractABTestManager:null,
		AbstractReportParameter:null,
		AbstractPageReportResponseLogEntry:null
	},
	constants:{
		viewTypes:{
			COMMON_VIEW:"common",
			FRAMESET_VIEW:"frameset",
			ERROR_PAGE_VIEW:"errorPage",
			CATEGORY_SEARCH_VIEW:"categorySearch",
			CATEGORY_VIEW:"category",
			SITE_SEARCH_VIEW:"siteSearch",
			PRODUCT_LOADER_VIEW:"productLoader",
			PRODUCT_VIEW:"product",
			PRODUCT_IMAGE_LOADER_VIEW:"productImageLoader",
			VIEW_LARGER_VIEW:"viewLarger",
			ALT_VIEWS_VIEW:"altViews",
			ZOOM_VIEW_VIEW:"zoomView",
			QUICKLOOK_VIEW:"quicklook",
			OUTFIT_VIEW:"outfit",
			INLINE_BAG_ADD_VIEW:"inlineBagAdd",
			SHOPPING_BAG_VIEW:"shoppingBag",
			FIRST_CHECKOUT_PAGE_VIEW:"firstCheckoutPage",
			CHECKOUT_ORDER_MODULE_VIEW:"checkoutOrderModule",
			ORDER_CONFIRM_VIEW:"orderConfirm",
            ERROR_VIEW:"error",
            REVIEWS_WRAPPER_VIEW:"reviewsWrapper",
            REVIEWS_PROFILE_VIEW:"reviewsProfile",
            REVIEWS_VOTE_VIEW:"reviewsVote",
            SWATCH_ENGAGEMENT_VIEW:"swatchEngagement",
            CATEGORY_FACETED_SEARCH_VIEW:"categoryFacetedSearch"
        },
        parameterNames:{
        	VIEW_TYPE_PARAMETER_NAME:"viewType"
        },
		reportingServiceTypes:{
			REPORTING_SERVICE_TYPE_G:"g",
			REPORTING_SERVICE_TYPE_H:"h"
		}
	}
}

var reportingService = new ReportingService();
reportingService.controller.AbstractReportViewManager = Class.create();
reportingService.controller.AbstractReportViewManager.prototype = {
	reportName:null,
	isReadyForTransmission:false,
	isWaitReport:false,
	isWaitComplete:false,
	initialize:function() {
		//initialize properties here
	},
	model: {},
	controller: {
		setReportModel:null,
		setReportTransmissionVars:null,
		setCleanUp:null
	}
}

reportingService.controller.AbstractReportAppManager = Class.create();
reportingService.controller.AbstractReportAppManager.prototype = {
	reportName:null,
	initialize:function() {
		//initialize properties here
	},
	model: {},
	controller: {
		setReportModel:null,
		setReportTransmissionVars:null
	}
}

reportingService.controller.AbstractReportProcessingLog = Class.create();
reportingService.controller.AbstractReportProcessingLog.prototype = {
	reportRegistry:[],
	reportsToClean:[],
	reportsWaiting:[],
	reportParameterRegistry:[],
	reportTime:null,
	initialize:function() {
		//initialize properties here
	}
}

reportingService.controller.AbstractPageReportResponseLogEntry = Class.create();
reportingService.controller.AbstractPageReportResponseLogEntry.prototype = {
	pageReportResponse:null,
	reportTime:null,
	pageReportUrl:null,
	initialize:function() {
		//initialize properties here
	}
}

reportingService.controller.AbstractOmniStub = Class.create();
reportingService.controller.AbstractOmniStub.prototype = {
	strCurrentPageName:null,
	initialize:function() {
		//initialize properties here
	}
}

reportingService.controller.AbstractReportParameter = Class.create();
reportingService.controller.AbstractReportParameter.prototype = {
	parameterName:null,
	parameterValue:null,
	initialize:function() {
		//initialize properties here
	}
}

Object.extend(
	reportingService.controller.init, {
		main:function() {
			processingService.api.addApplicationMethodToRegistry(this.setDomReadyHandler, "reporting service");
			Event.observe(document, "personalizationData:ready", this.personalizationDataReadyHandler);
			// Create instance of OmniStub class for WCD code.  This code
			// will be deprecated over time as WCD cleans it's code to H code
			// standard.
			omni = new reportingService.controller.AbstractOmniStub();
		},
		setDomReadyHandler:function() {
			var isPersonalizationDataReady = reportingService.model.isPersonalizationDataReady;
			var reportingServiceReadyHandler = reportingService.controller.init.reportingServiceReadyHandler;
			if (isPersonalizationDataReady) {
				reportingServiceReadyHandler();
			} else {
				Event.observe(document, "personalizationData:ready", reportingServiceReadyHandler);
			}
		},
		personalizationDataReadyHandler:function() {
			reportingService.model.isPersonalizationDataReady = true;
		},
		reportingServiceReadyHandler:function() {
			var reportingManager = reportingService.controller.reportingManager;
			var categoryOrCheckoutRegExp = /(browse\/search\.do)|(browse\/category(Search)?\.do)|(checkout\/order\.do)/;

			var isFacetedCategoryPage = window['reportingService'] && reportingService.controller.viewManagers.categoryFacetedSearchViewManager
			&& reportingService.controller.viewManagers.categoryFacetedSearchViewManager.controller;
			
			// If IE and on the search, category or checkout page, delay the omniture call
			if (clientBrowser.isIE6up && categoryOrCheckoutRegExp.test(window.location) && !isFacetedCategoryPage) {
				setTimeout("reportingService.controller.reportingManager.getReportingRequest()",1000);
			} else {
				reportingManager.getReportingRequest();
			}
		}
	}
);

Object.extend(
	reportingService.controller.reportingManager, {
		reportingAccount:null,
		currencyType:null,
		marketSpecificOmnitureUrl:null,
		marketSpecificSecureOmnitureUrl:null,
		registryHasWaitReports:false,
		pageReportResponseLog:[],
		reportProcessingLogs:[],
		pageReportTransmissionCount:0,
		isPageReportActive:true,
		isPageReportSingleTransmissionActive:false,
		inspectReportRegistry:function() {
            if(!window['s']) { return; }
			var reportingManager = reportingService.controller.reportingManager;
			var reportRegistry = reportingService.model.reportRegistry;
			var reportsWaiting = reportingService.model.reportsWaiting;
			var registryIterator = null;
			reportingManager.registryHasWaitReports = false;
			registryIterator = function(viewManager, registryIndex) {
				var viewManagerController = viewManager.controller;
				var reportName =  viewManager.reportName;
				var reportingManager = reportingService.controller.reportingManager;
				if (viewManager.isReadyForTransmission == false) {
					if ((viewManager.isWaitReport == true) && (viewManager.isWaitComplete == false)) {
						reportingManager.registryHasWaitReports = true;
						reportsWaiting.push(viewManager);
					}
					else {
						reportingManager.processReport(viewManager);
					}
				}
				else {
					// Report is ready for transmission.
					reportingManager.processReport(viewManager);
				}
			}

			reportRegistry.each(registryIterator);
			
			if (reportingManager.registryHasWaitReports == true) {
				// logService.info
			}
			else {
				/* No reportsWaiting found in registry inspection so transmit request
				 * immediately.
				 */
				
				// Override variables for AB Testing 
				reportingManager.setABTestingOverrideVariables();
				reportingManager.transmitRequest();
			}
		},
		processReport:function(viewManager) {
			var viewManagerController = viewManager.controller;
			var reportsToClean = reportingService.model.reportsToClean;
			if (viewManagerController) {
				if (viewManagerController.setReportModel && viewManagerController.setReportTransmissionVars) {
					viewManagerController.setReportModel();
					viewManagerController.setReportTransmissionVars();
					viewManager.isReadyForTransmission = true;
				}
				else {
					// logService.error(reportName + " does not have proper interface methods.");
				}
				if (viewManagerController.setCleanUp) {
					reportsToClean.push(viewManager);
				}
			}
		},
		setViewManagerToReportRegistry:function(viewManager) {
			var reportRegistry = reportingService.model.reportRegistry;
			var reportRegistrySize = null;
			var nextReportIndex = null;
			if (reportRegistry == null) {
				reportingService.model.reportRegistry = new Array();
				reportRegistry = reportingService.model.reportRegistry;
			}
			reportRegistry.push(viewManager);
		},
		getReportingRequest:function(viewManagers) {
			var reportingManager = reportingService.controller.reportingManager;
			var reportRegistry = reportingService.model.reportRegistry;
			var viewManager = null;
			if (viewManagers instanceof Array) {
				if (viewManagers) {
					for (var viewManagerCount = 0;viewManagerCount < viewManagers.length;viewManagerCount++) {
						viewManager = viewManagers[viewManagerCount];
						reportingManager.setViewManagerToReportRegistry(viewManager);
					}
				}
			}
			else if (viewManagers instanceof Object) {
				viewManager = viewManagers;
				reportingManager.setViewManagerToReportRegistry(viewManager);
			}
			reportingManager.inspectReportRegistry();
		},
		/**
		 * setABTestingOverrideVariables reads values from a globally scoped object to override values.
		 * 
		 * Modified 8/26/09 Byung -- relaxed the eVar restriction to allow overriding of any value 
		 */
		setABTestingOverrideVariables:function() {
			if (window["ABTestVariables"]) {
				var evars = Object.keys(ABTestVariables);
				evars.each(function(evar) {
					if (evar) s[evar] = ABTestVariables[evar];
				});
			}
		},
		transmitRequest:function() {
			/* Omniture sCode transmission code here.
			 * After transmission call the setCleanUp() method on each viewManager in the reportRegistry.
			 * After setCleanUp clear the reportRegistry, reportsToClean, reportsWaiting, and reportParameterRegistry.
			 */
			var reportingManager = reportingService.controller.reportingManager;
			var reportRegistry = reportingService.model.reportRegistry;
			var reportsToClean = reportingService.model.reportsToClean;
			var reportsWaiting = reportingService.model.reportsWaiting;
			var reportParameterRegistry = reportingService.model.reportParameterRegistry;
			var reportProcessingLogs = reportingService.controller.reportingManager.reportProcessingLogs;
			var reportsToCleanIterator = null;
			var reportProcessingLog = null;
			
			reportingManager.sendAnalyticsEvent();
			
			reportsToCleanIterator = function(viewManager, reportIndex) {
				if (viewManager.controller.setCleanUp) {
					viewManager.controller.setCleanUp();
				}
			}
			
			reportsToClean.each(reportsToCleanIterator);
			reportProcessingLog = new reportingService.controller.AbstractReportProcessingLog();
			reportProcessingLog.reportRegistry = reportRegistry;
			reportProcessingLog.reportsToClean = reportsToClean;
			reportProcessingLog.reportsWaiting = reportsWaiting;
			reportProcessingLog.reportParameterRegistry = reportParameterRegistry;
			reportProcessingLog.reportTime = new Date();
			reportProcessingLogs.push(reportProcessingLog);

			reportingService.model.reportRegistry = new Array();
			reportingService.model.reportsToClean = new Array();
			reportingService.model.reportsWaiting = new Array();
			// reportingService.model.reportParameterRegistry = new Array();
			
		},
		sendAnalyticsEvent:function() {
			var reportingManager = reportingService.controller.reportingManager;
			var pageReportTransmissionCount = reportingManager.pageReportTransmissionCount;
			var isPageReportActive = reportingManager.isPageReportActive;
			var isPageReportSingleTransmissionActive = reportingManager.isPageReportSingleTransmissionActive;
			
			reportingManager.sendAnalyticsEventForOmniReport();
			
			if (isPageReportActive) {
				/* Only transmit a single pageReport transmission per page for initial release,
				 * and subsequent to release check the boolean flag isPageReportSingleTransmissionActive*/
				if (isPageReportSingleTransmissionActive && pageReportTransmissionCount < 1) {
					reportingManager.sendAnalyticsEventForPageReport();
					reportingManager.pageReportTransmissionCount++;
				} else {
					reportingManager.sendAnalyticsEventForPageReport();
					reportingManager.pageReportTransmissionCount++;
				}
			}
		},
		sendAnalyticsEventForOmniReport:function() {
			/* Process Omni request */
			var omniDiv = $('omniSendAnalytics');
		
			if (!omniDiv) {
				omniDiv = document.createElement('div');
				omniDiv.id = "omniSendAnalytics";
				omniDiv.setAttribute('omniIndex', 0)
				document.body.appendChild(omniDiv);
			}
			s_code = s.t();
			var index = parseInt(omniDiv.getAttribute('omniIndex')||0);
			var indexStr = index ? '_' + index : '';
			var omniPixel = window['s_i_' + s.visitorNamespace + indexStr];
			if (omniPixel || s_code) {
				var index = index + 1;
                var content = $('omniSendAnalytics').innerHTML;
				omniDiv.innerHTML = (omniPixel.src || s_code);
				omniDiv.setAttribute('omniIndex', index);
			}
		},
		sendAnalyticsEventForPageReport:function() {
			/* Process pageReport request */
			var reportingManager = reportingService.controller.reportingManager;
			var pageReportUrl = reportingManager.getPageReportUrl();
			
			if (pageReportUrl != null) {
				new Ajax.Request(pageReportUrl, {
						method:"get",
						onSuccess: function(transport) {
							var pageReportResponseLog = reportingManager.pageReportResponseLog;
							var pageReportResponse = transport.responseJSON;
							if (pageReportResponse) {
								var pageReportResponseLogEntry = new reportingService.controller.AbstractPageReportResponseLogEntry();
								pageReportResponseLogEntry.pageReportResponse = pageReportResponse;
								pageReportResponseLogEntry.reportTime = new Date();
								pageReportResponseLogEntry.pageReportUrl = pageReportUrl;
								pageReportResponseLog.push(pageReportResponseLogEntry);
							}
						}
					}
				);
			}
		},
		getPageReportUrl:function() {
			var pageReportUrl = null;
			var reportParameterRegistry = reportingService.model.reportParameterRegistry
			var reportParametersFormattedForRequest = "";
			var reportParameterPrefix = "";
			var pageNameParameter = reportingService.model.reportParameterMap["p1"];
			if (pageNameParameter != null && pageNameParameter != undefined) {
				var pageName = reportingService.model.reportParameterMap["p1"].parameterValue;
				
				/* Remove all forward and backward slashes from pageName included in URI.  
				 * Url encoded, they cause 400 errors from apache
				 */
				pageName = pageName.replace(/[\\\/]/g,"");
				
				var pageNameEncoded = encodeURIComponent(pageName);
				var reportParameterRegistryIterator = function(reportParameter, reportParameterIndex) {
					if (reportParameter) {
						if (reportParameterIndex > 0) {
							reportParameterPrefix = "&";
						} else {
							reportParameterPrefix = "?";
						}
						var parameterName = reportParameter.parameterName;
						var parameterValue = encodeURIComponent(reportParameter.parameterValue);
						if (reportParameter.parameterName == "pagePath") {
							parameterValue = escape(reportParameter.parameterValue);
						}
						reportParametersFormattedForRequest = reportParametersFormattedForRequest + reportParameterPrefix + parameterName + "=" + parameterValue;
					}
				}
				reportParameterRegistry.each(reportParameterRegistryIterator);
				/* sem */
				var isReferrerAThirdPartySite = personalizationService.controller.isReferrerAThirdPartySite();
				var SEM_PARAMETER = personalizationService.constants.requestParameters.SEM_PARAMETER;
				var semParameter = gidLib.getQuerystringParam(SEM_PARAMETER, true);
				var semParameterValue = null;
				if (semParameter == "true") {
					semParameterValue = encodeURIComponent(semParameter);
				} else if (isReferrerAThirdPartySite){
					semParameterValue = "true";
				}
				if (semParameterValue != null) {
					reportParametersFormattedForRequest = reportParametersFormattedForRequest + "&" + SEM_PARAMETER + "=" + semParameterValue;
				}
				/* prototcol */
				var requestProtocol = null;
				var requestHost = window.location.host;
				if (window.location.protocol == "http:") {
					requestProtocol = "http:";
				} else {
					requestProtocol = "https:";
				}
				pageReportUrl = requestProtocol + "//" + requestHost + "/resources/metrics/pageReport/v1/" + pageNameEncoded + reportParametersFormattedForRequest;
			}
			
			return pageReportUrl;
		},
		setReportParameterToReportParameterRegistry:function(reportParameter) {
			var reportingManager = reportingService.controller.reportingManager;
			var validator = reportingManager.validator;
			var reportParameterRegistry = reportingService.model.reportParameterRegistry;
			var reportParameterMap = reportingService.model.reportParameterMap;
			var isReportParameterValid = validator.isReportParameterValid(reportParameter);
			if (isReportParameterValid) {
				/* Check if the parameter is already created, and if so then update the existing parameter, otherwise create a new parameter */
				var parameterName = reportParameter.parameterName;
				var parameterValue = reportParameter.parameterValue;
				var reportParameterRegistered = reportParameterMap[parameterName];
				if (reportParameterRegistered) {
					/* reportParameter exists, so update value */
					reportParameterRegistered.parameterValue = parameterValue + "";
				} else {
					/* reportParameter does not exist, so register. */
					reportParameterRegistry.push(reportParameter);
					reportParameterMap[reportParameter.parameterName] = reportParameter;
				}
			}
		},
		setReportParameter:function(parameterName, parameterValue) {
			var reportingManager = reportingService.controller.reportingManager;
			var reportParameter = new reportingService.controller.AbstractReportParameter();
			reportParameter.parameterName = parameterName;
			reportParameter.parameterValue = parameterValue;
			reportingManager.setReportParameterToReportParameterRegistry(reportParameter);
			return reportParameter;
		},
		validator:{
			isReportParameterValid:function(reportParameter) {
				var isReportParameterValid = false;
				var reportParameterRegistry = reportingService.model.reportParameterRegistry;
				var reportingManager = reportingService.controller.reportingManager;
				var validator = reportingManager.validator;
				if (reportParameter != null && reportParameter != undefined && reportParameterRegistry != null) {
					var parameterName = reportParameter.parameterName;
					var parameterValue = reportParameter.parameterValue;
					var isParameterNameValid = validator.isStringNotEmpty(parameterName);
					var isParameterValueValid = validator.isStringNotEmpty(parameterValue);
					if (isParameterNameValid && isParameterValueValid) {
						isReportParameterValid = true;
					}
				}
				return isReportParameterValid;
			},
			isStringNotEmpty:function(testValue) {
				var isStringNotEmpty = false;
				if (testValue != null) {
					var testValueString = testValue + "";
					if (testValueString.length > 0) {
						isStringNotEmpty = true;
					}
				}
				return isStringNotEmpty;
			}
		}
	}
);

Object.extend(
	reportingService.api, {
		setReportParameter:function(parameterName, parameterValue) {
			var reportingManager = reportingService.controller.reportingManager;
			var reportParameter = reportingManager.setReportParameter(parameterName, parameterValue);
			return reportParameter;
		},
		setViewTypeReportParameter:function(viewTypeValue) {
            var VIEW_TYPE_PARAMETER_NAME = reportingService.constants.parameterNames.VIEW_TYPE_PARAMETER_NAME;
            var viewTypeReportParameter = reportingService.api.setReportParameter(VIEW_TYPE_PARAMETER_NAME, viewTypeValue);
            return viewTypeReportParameter;
		}
	}
);
reportingService.controller.init.main();

// Initialize the AB Test variables object
if (!window["ABTestVariables"]) var ABTestVariables = {};

