HD.Login = function(config) {
	this.model = new HD.Login.Model(config);
	this.view = new HD.Login.View(this.model);
	this.controller = new HD.Login.Controller(this.model, this.view);	
	
	registerWait = new YAHOO.widget.Panel("registerWait",   
        { width: "32px",		  
          fixedcenter:true,  
          close:false,  
          draggable:false,  
          zindex:200000, 
          modal:true,
          underlay: 'none',
          visible:false 
        }  
    );
	
	registerWait.setHeader('');
	registerWait.setBody('<img src="' + comMediaBaseUrl + '/hd/hd_login/assets/skins/hd/loading.gif"/>');  
	registerWait.render(document.body);
};

HD.Login.ANONYMOUS_USER_NAME = "anonymousUser";

HD.Login.Model = function(config) {	
	this.config = config;
	this.events = {
		registered : new HD.util.Event("registered"),
		authenticated : new HD.util.Event("authenticated"),
		screenNameCreated: new HD.util.Event("screenNameCreated")		
	};
	this.ready = true;
	this.queue = [];
	
	this.observers = [];
};

HD.Login.Model.prototype = {
	ANONYMOUS : "anonymous",
	REGISTERED : "registered",
	AUTHENTICATED : "authenticated",
	
	publicSites : [
		/^https?:\/\/www\.harley-davidson\.com.*/,
		/^https?:\/\/www\.buell\.com.*/,
		/^https?:\/\/members\.hog\.com.*/
	],
	
	queueRequest : function(request) {
		// Add request functions to the queue if necessary.
		if (!this.ready) {
			this.queue.push(request);
		}
		else {
			request();
		}
	},
	
	processQueue : function(userResponse) {
		// Execute every function in the queue.
		if (this.ready) {
			while (this.queue.length > 0) {
				this.queue.shift()(userResponse);
			}
		}
	},
	
	setRpc : function() {
		this.rpcType = DWREngine._rpcType;
		this.path = UserService._path;
		
		if(this.isPublicSite()) {
			var serverUrl = HD.util.Common.getServerUrl();
			if(serverUrl.indexOf("https") != 0) {
				serverUrl = serverUrl.replace(/http/, "https");
			}
			UserService._path = serverUrl + UserService._path;
			
			DWREngine.setMethod(DWREngine.ScriptTag);
		}
	},
	
	resetRpc : function() {
		DWREngine.setMethod(this.rpcType);
		UserService._path = this.path;
	},
	
	isPublicSite : function() {
		var serverUrl = HD.util.Common.getServerUrl();
		
		for(var i = 0, len = this.publicSites.length; i < len; i++) {
			if(serverUrl.match(this.publicSites[i])) {
				return true;
			}
		}
		
		return false;
	},
	
	getUser : function(callback) {
		this.notifyObservers("getUser_Start");
		var cb = this;
		var userRequest = {};
		this.setFilters(userRequest);
		UserService.getLoggedInStatus(userRequest, function(userResponse){
			if (callback) callback(userResponse);
			cb.notifyObservers.call(cb, "getUser_Finish", userResponse);
		});
	},
	
	init : function(callback, forceLogin) {
		// Handle forced logins
		this.forceLogin = !!forceLogin;
		this.ready = !this.forceLogin || false;
		if (this.forceLogin) {
			var userCallback = callback || function() {};
			callback = function() {
				userCallback();
				// Keep retrying until a user is found.
				(function tryGetUser() {
					cb.getUser(function(userResponse) {
						if (userResponse.loggedInLevel > 1) {
							cb.ready = true;
							cb.processQueue(userResponse);
						}
						else {
							// Try again.
							setTimeout(function() {
								tryGetUser();
							}, 250);
						}
					});
				})();
			};
		}
		
		var cb = this;
		this.notifyObservers("loginInit_Start");
		UserService.getIlCookies(function(response){
			var returnurl = HD.util.Common.getServerUrl() + "/Community/services/ILInit/?secret=" + HD.util.Common.timestamp();
			var url = response.profile +"/cpapp/auth/ILTicket.h-d?nologin=1&ret_uri=" + escape(returnurl);
			HD.util.Common.addImage(url, callback || null);
			cb.notifyObservers("loginInit_Finish", HD.merge(response, { returnUrl: returnurl }));
		});
	},
	
	authenticate : function(user) {
		this.setRpc();
		var cb = this;
		var userRequest = {user:user};
		this.setFilters(userRequest);
		UserService.authenticate(userRequest, function(userResponse){
			cb.handleAuthenticate.call(cb, userResponse);
			registerWait.hide();
		});
		registerWait.show();
		this.resetRpc();
	},
	
	handleAuthenticate : function(user) {
		if(user!=null){
			if ((user.user.screenName == null) && (user.user.ilTicket != null)){
				this.events.screenNameCreated.fire(user);
			} else {
				this.events.authenticated.fire(user);
			}
		}		
	},
	
	register : function(user) {
		this.setRpc();
		var cb = this;
		var u = user;
		var userRequest = {user:user};
		this.setFilters(userRequest);
		UserService.register(userRequest, function(userResponse){
			cb.handleRegister.call(cb, userResponse);
			registerWait.hide();
		});
		var scrollable = HD.get("hdwcBody");
		registerWait.show();
		this.resetRpc();
	},
	
	handleRegister : function(userResponse) {
		this.events.registered.fire(userResponse);
	},
	
	checkScreenName : function(user) {
		var cb = this;
		var u = user;
		var userRequest = {user:user};
		this.setFilters(userRequest);
		UserService.checkScreenname(userRequest, function(userResponse){
			cb.handleCheckScreenName.call(cb, userResponse);
			registerWait.hide();
		});
		registerWait.show();
	},
	
	handleCheckScreenName : function(userResponse) {		
		this.events.registered.fire(userResponse);		
	},
	
	checkScreenNameCreate : function(user) {
		var cb = this;
		var u = user;
		var userRequest = {user:user};
		this.setFilters(userRequest);
		UserService.checkScreenname(userRequest, function(userResponse){
			cb.handleCheckScreenNameCreate.call(cb, userResponse);
			registerWait.hide();
		});
		registerWait.show();
	},
	
	handleCheckScreenNameCreate : function(userResponse) {		
		this.events.screenNameCreated.fire(userResponse);		
	},
	
	createScreenName : function(user) {
		var cb = this;
		var u = user;
		var userRequest = {user:user};
		this.setFilters(userRequest);
		UserService.createScreenName(userRequest, function(userResponse){
			cb.handleCreateScreenName.call(cb, userResponse);
			registerWait.hide();
		});
		registerWait.show();
	},
	
	handleCreateScreenName : function(userResponse) {		
		this.events.screenNameCreated.fire(userResponse);	
	},
	
	setFilters : function(request) {
		request.siteName = this.config.siteName;
	},
	
	isUserLoggedIn : function(callback) {
		var userRequest = {};
		this.setFilters(userRequest);
		this.queueRequest(function(response) {
			if (!!response) {
				callback(response);
			}
			else {
				UserService.getLoggedInStatus(userRequest, function(userResponse){
					callback(userResponse);
				});
			}
		});
	}
};

HD.extend(HD.Login.Model, [HD.util.Observable]);

HD.Login.View = function(model){
	this.content = HD.Login.Content;
	this.model = model;
	this.config = model.config;
	
	this.AUTHENTICATE_FORM_ID = "hdAuthenticateForm";
	this.AUTHENTICATE_SUBMIT_ID = "hdAuthenticateSubmit";
	this.REGISTER_FORM_ID = "hdRegisterForm";
	this.REGISTER_SUBMIT_ID = "hdRegisterSubmit";
	this.CHECK_SCREENNAME_ID = "hdCheckScreenname";
	
	this.events = {
		registerClick : new HD.util.Event("registerClick"),
		authenticateClick : new HD.util.Event("authenticateClick"),
	    screennameCheckClick : new HD.util.Event("screennameClick"),
	    checkSNCreateClick : new HD.util.Event("checkSNCreateClick"),
		createScreenNameClick : new HD.util.Event("createScreenNameClick")
	};
	
	var cb = this;
	this.model.events.authenticated.subscribe(function(userResponse){cb.handleAuthenticated.call(cb, userResponse)});
	this.model.events.registered.subscribe(function(userResponse){cb.handleRegistered.call(cb, userResponse)});
	this.model.events.screenNameCreated.subscribe(function(userResponse){cb.handleScreenNameCreated.call(cb, userResponse)});
	
	this.observers = [];
	
	this.model.addObserver(this);
};

HD.Login.View.prototype = {
	update : function(eventName, eventData) {
		var cb = this;
		if(eventName == "getUser_Finish") {
			cb.loginStatus.call(cb, eventData);
		}
	},
		
	loginStatus : function(userResponse) {
		var eventName = "notLogged_In";
		
		if(userResponse != null){
			if(userResponse.loggedInLevel > 1){
				eventName = "logged_In";
			}
		}
		
		this.model.notifyObservers(eventName, userResponse);
	},
	
	showForm : function(formConfig) {
		var cb = this;
		var fConfig = formConfig;
		var timestamp = HD.util.Common.timestamp();
		registerWait.show();
		HD.util.Common.requestContent(formConfig.getContent() + "?siteName=" + comSiteName + "&timestamp=" + timestamp, function(responseText) {				
			var overlayEl = HD.util.Common.showOverlay(responseText, fConfig.title, fConfig.width, fConfig.height);			
			cb.setupListeners.call(cb, overlayEl, fConfig);
			registerWait.hide();			
		});
		// send string of path instead of body contents << use for iframes
		//var overlayEl = HD.util.Common.showOverlay(formConfig.getContent(), fConfig.width, fConfig.height);			
		//cb.setupListeners.call(cb, overlayEl, fConfig);
	},
	
	showFormScrolled : function(formConfig) {
		var cb = this;
		var fConfig = formConfig;
		var timestamp = HD.util.Common.timestamp();
		registerWait.show();
		HD.util.Common.requestContent(formConfig.getContent() + "?siteName=" + comSiteName + "&timestamp=" + timestamp, function(responseText) {
		var overlayEl = HD.util.Common.showOverlay(responseText, fConfig.title, fConfig.width, fConfig.height);
		
		// send string of path instead of body contents << use for iframes
		//var overlayEl = HD.util.Common.showOverlay(formConfig.getContent(), fConfig.width, fConfig.height);			
		//cb.setupListeners.call(cb, overlayEl, fConfig);
		
		cb.setupListeners.call(cb, overlayEl, fConfig);
		
		var scrollable = HD.get("hdwcBody");
		var offset = HD.get("formBottom").offsetTop;
		scrollable.scrollTop = offset;
		registerWait.hide();		
		});
	},
	
	setupListeners : function(overlayEl, fConfig) {
		var formEl = HD.get(fConfig.id);
		var cb = this;
		
		if(formEl != null){
			formEl.onsubmit = function() {
				HD.addClass(formEl, "hdFormLoading");
				cb[fConfig.callback].call(cb, formEl);
				return false;
			};
		}		
		
		var closeEls = HD.getByClass("hdShowRegister", "div", overlayEl);
		if(closeEls != null && closeEls.length > 0) {			
			closeEls[0].onclick = function() {	
				cb.promptRegistration.call(cb);
			};
		}
		
		closeEls = HD.getByClass("hdLogout", "div", overlayEl);		
		if(closeEls != null && closeEls.length > 0) {
			closeEls[0].onclick = function() {				
				cb.logoutUser.call(cb);
				HD.util.Common.hideOverlay();
			};
		}
	},
	
	promptCreateScreenName : function(){
		HD.util.Analytics.track(this.analyticsScreenNameString());
		this.showForm(this.content.SCREENNAME);
	},
	
	onScreenNameSubmit : function(form) {		
		var user = this.collectUserData(form);		
		if ((form.checkingScreenname.value == "true")){			
			this.events.checkSNCreateClick.fire(user);
		} else {			
			this.events.createScreenNameClick.fire(user);
		}
	},	
	
	promptAuthentication : function() {
		HD.util.Analytics.track(this.analyticsAuthenticateString());
		this.showForm(this.content.AUTHENTICATE);
	},
	
	onAuthenticationSubmit : function(form) {
		var user = this.collectUserAuthenticateData(form);
		this.events.authenticateClick.fire(user);
	},
	
	promptRegistration : function() {
		HD.util.Analytics.track(this.analyticsRegisterString());
		this.showForm(this.content.REGISTER);
	},
	
	logoutUser : function() {
		UserService.clearSessionUserInfo();
		UserService.logoutUser();
		this.loginStatus();
//		registerWait.hide();
		var cb = this;
		UserService.getIlCookies(function(response){
			var timestamp = HD.util.Common.timestamp();
			HD.util.Common.addImage(response.hdLogout +"?timestamp=" + timestamp);
			HD.util.Common.addImage(response.buellLogout +"?timestamp=" + timestamp);
			HD.util.Common.addImage(response.hogLogout +"?timestamp=" + timestamp);
			HD.util.Common.addImage(response.rideplannerLogout +"?timestamp=" + timestamp);
			HD.util.Common.addImage(response.profile + "/cpapp/ilCookie/delete/");
			cb.model.notifyObservers.call(cb.model, "notLogged_In");
		});
	},
	
	onRegistrationSubmit : function(form) {		
		var user = this.collectUserData(form);		
		if ((form.checkingScreenname.value == "true")){			
			this.events.screennameCheckClick.fire(user);
		} else {			
			this.events.registerClick.fire(user);
		}		
	},	
	
	showLogoutOverlay : function() {		
		this.showForm(this.content.LOGOUT);
	},
	
	handleAuthenticated : function(userResponse) {
		var cb = this;
		var user = userResponse.user;
		if(userResponse.loggedInLevel == 0) {
			this.showForm(this.content.AUTHENTICATE);
		} else if(userResponse.loggedInLevel == 1){
			this.showForm(this.content.SCREENNAME);			
		} else {
			HD.util.Common.hideOverlay();
			cb.loginStatus(userResponse);
			cb.writeCookies(user);
			HD.util.Analytics.track(this.analyticsAuthenticateConfirmString());
		}
	},
	
	handleRegistered : function(userResponse) {
		var user = userResponse.user;
		var errors = userResponse.errors;
		var screenNameCheck = userResponse.screenNameCheck;
		var cb = this;
		if((errors == null || errors.length < 1) && !screenNameCheck) {
			HD.util.Common.hideOverlay();
			HD.util.Analytics.track(this.analyticsRegisteredString());
			cb.showForm(this.content.CONFIRMATION);
			cb.loginStatus(userResponse);
		} else if(screenNameCheck){			
			this.showFormScrolled(this.content.REGISTER);
		} else {
			this.showForm(this.content.REGISTER);
		}
	},
	
	handleScreenNameCreated : function(userResponse) {
		var user = userResponse.user;
		var errors = userResponse.errors;
		var screenNameCheck = userResponse.screenNameCheck;
		if((errors == null || errors.length < 1) && !screenNameCheck && (user != null) && (user.screenName != null)) {
			HD.util.Common.hideOverlay();	
			this.loginStatus(userResponse);
		} else {
			this.showForm(this.content.SCREENNAME);
		}
	},
	
	collectUserData : function(form) {
		var user = {};		
		if(form.hdwcPassword != null) {
			user.password = form.hdwcPassword.value;
		}
		if(form.hdwcPassword2 != null) {
			user.passwordConfirm = form.hdwcPassword2.value;
		}
		if(form.hdwcFirstName != null) {
			user.firstName = form.hdwcFirstName.value;
		}
		if(form.hdwcMiddleName != null) {
			user.middleName = form.hdwcMiddleName.value;
		}
		if(form.hdwcLastName != null) {
			user.lastName = form.hdwcLastName.value;
		}
		if(form.hdwcEmailAddress != null) {
			user.email = form.hdwcEmailAddress.value;
			//Username will be the same as the e-mail address going forward 
			user.userName = form.hdwcEmailAddress.value;
		}
		if(form.hdwcSelectMonth != null && 
				form.hdwcSelectDay != null && form.hdwcSelectYear != null) {
			// Must format the date to a strick MM/yy/dd otherwise the validation will fail
			if(form.hdwcSelectMonth.value.length > 0 
					&& form.hdwcSelectDay.value.length > 0 && form.hdwcSelectYear.value.length > 0) {
				var tmpDob = form.hdwcSelectMonth.value.length < 2 ? "0" + 
						form.hdwcSelectMonth.value + "/": form.hdwcSelectMonth.value + "/";
				tmpDob += form.hdwcSelectDay.value.length < 2 ? "0" + 
						form.hdwcSelectDay.value + "/": form.hdwcSelectDay.value + "/";
				tmpDob += form.hdwcSelectYear.value;
				
				user.dob = tmpDob;				
			}			
		}
		if(form.optIn != null) {
			user.optIn = form.optIn.checked;
		}		
		if(form.screenName != null) {
			user.screenName = form.screenName.value;				
		}
		if(form.hdwcZip != null) {
			user.zip = form.hdwcZip.value;				
		}
		
		return user;
	},
	
	collectUserAuthenticateData : function(form) {
		var user = {};		
		if(form.password != null) {
			// IL doesn't have functionality to validate passwords - throwing in a hook of our own
			user.password = form.password.value;				
		}
		
		if(form.email != null) {
			user.email = form.email.value;
			//Username will be the same as the e-mail address going forward 
			user.userName = form.email.value;
		}
		return user;
	},
	
	writeCookies : function(user) {	
		var cb = this;
		cb.user = user;
		UserService.getIlCookies(function(response){
			var timestamp = HD.util.Common.timestamp();
			HD.util.Common.addImage(response.hdLogin +"?timestamp=" + timestamp);
			HD.util.Common.addImage(response.buellLogin +"?timestamp=" + timestamp);
			HD.util.Common.addImage(response.hogLogin +"?timestamp=" + timestamp);
			HD.util.Common.addImage(response.rideplannerLogin +"?timestamp=" + timestamp);
			HD.util.Common.addImage(response.profile + "/cpapp/ilCookie/add/" + cb.user.ilTicket +"/" +cb.user.userName);
		});
	},
	
	analyticsAuthenticateString : function() {
		return "default_analyticsAuthenticateString";
	},
	
	analyticsRegisterString : function() {
		return "default_analyticsRegisterString";
	},
	
	analyticsRegisteredString : function() {
		return "default_analyticsRegisteredString";
	},
	
	analyticsScreenNameString : function() {
		return "default_analyticsScreenNameString";
	},
	
	analyticsAuthenticateConfirmString : function() {
		return "default_analyticsAuthenticateConfirmString";
	}	
	
};

HD.extend(HD.Login.View, [HD.util.Observable]);

HD.Login.Controller = function(model, view){
	this.model = model;
	this.view = view;
	
	var cb = this;
	this.view.events.registerClick.subscribe(function(user){cb.handleRegister.call(cb, user)});
	this.view.events.authenticateClick.subscribe(function(user){cb.handleAuthenticate.call(cb, user)});	
	this.view.events.screennameCheckClick.subscribe(function(user){cb.handleCheckScreenname.call(cb, user)});
	this.view.events.checkSNCreateClick.subscribe(function(user){cb.handleCheckSNCreate.call(cb, user)});
	this.view.events.createScreenNameClick.subscribe(function(user){cb.handleCreateScreenName.call(cb, user)});
};

HD.Login.Controller.prototype = {
	authenticateUser : function() {
		this.view.promptAuthentication();
	},
	
	registerUser : function() {
		this.view.promptRegistration();
	},
	
	handleRegister : function(user) {
		this.model.register(user);
	},
	
	handleAuthenticate : function(user) {
		this.model.authenticate(user);
	},
	
	handleCheckScreenname : function(user) {
		this.model.checkScreenName(user);
	},
	
	handleCheckSNCreate : function(user) {
		this.model.checkScreenNameCreate(user);
	},
	
	handleCreateScreenName : function(user) {
		this.model.createScreenName(user);
	}
};

HD.register('hd_login_widget', 'HD.Login', {version: "1.0", build: "1"});