/**
 * This object handles the cross domain login dialog process
 * @namespace
 */
m2.widget.user.Login = {

    HTML : {
		oidDialog :
		'<div id="oidHiddenDialog" style="display:none;">' + 
			'<form name="OIDLoginForm" method="POST" action="" id="oidtabform">' +
	        	'<input type="hidden" name="succUrl" value="${succUrl}">' +
	        	'<input type="hidden" name="f" value="qs">' +
			'</form>' +
		'</div>'
    },

	/**
	 * @property {Object} securidChallenge  the challenge object sent from sns when secure id login is required
	 * @scope httpsChild
	 */
	securidChallenge : null,

	/**
	 * @property {boolean} isLoginInit keeps track of the initialization state of the login box
	 * @scope httpParent
	 */
	isLoginInit : false,
    
    /**
     * Omniture screen name
     */
    _screen : null,
    
	/**
	 * Function will show the login dialog
	 * @scope httpParent
	 */
	showLoginDialog : function() {
        $a('MQ08MySignIn');        
		this.isLoginInit = false;
		// open the dialog
		this.dialog = m2.dialog.open({
			dialogName : "loginDialog",
			content : '<div style="text-align:center;font-weight:bold;" id="iframeLoadingMessage">' + m2.Label.Loading + '...</div>',
			modal : true,
			closeOthers : true,
			showCloseButton : false,
			size : {width:300,height:44},
			closeOnBackgroundClick : false,
			allowOverflow : false
		});
        
		// create the login frame
		m2.util.Iframe.create({
			id    : "loginFrame",
			src   : m2.util.getSecureUrl() + "/login#" + m2.util.toJson(m2.util.getBaseUrlForHash()),
			// NOTE: Position absolute is required or the page will jump around as the frame gets added to the 
			// end of the document
			style : {height:"1px",width:"280px",position:"absolute",scrolling:"no",overflow:"hidden"},
			node  : this.dialog.contentEl
		});
	},

	/**
	 */
	showAOLSignInDialog : function() {
        $awsn('MQ08MyAOLTab', this._screen);
		m2.$("aolLoginTab").style.display = "block";
		m2.$("openIDLoginTab").style.display = "none";
		this.initLogInForm();
		m2.util.Iframe.sendDocumentDimensions(true);
	},
		
	
	/**
	 */
	showOpenIDSignInDialog : function() {
        $awsn('MQ08MyOpenIDTab', this._screen);
		m2.$("aolLoginTab").style.display = "none";
		m2.$("openIDLoginTab").style.display = "block";
		this.initLogInForm();
		m2.util.Iframe.sendDocumentDimensions(true);
	},	
	
	/**
	 * This function is called from the https child frame to initialze the dialog
	 * @param {Object} data  The data object from the httpsChild.  Contains the dialog size.
	 * @scope httpParent
	 */
	initLoginDialog : function(data) {
		// This check is necessary because the updateDialogContent method causes the iframe to reload, and 
		// thus this will be called mulitple times.
		if (this.isLoginInit) {
			// The data always has the dimensions of the dialog so update the size.
			m2.dialog.update(data, "loginDialog");
			return;
		}
		var self = this;
		var  l = m2.$("iframeLoadingMessage");
		l.parentNode.removeChild(l);
		var f = m2.$("loginFrame");
		f.style.width = "280px";
		f.style.height = data.size.height + 50 + "px";
		// toggle display so the content positions properly
		f.style.position = "static";
		f.style.display = "block";
		f.style.scrolling = "no";
		f.style.frameborder = "0";
		m2.util.setStyle(f,"opacity",100);
			
		// animate the dialog to the correct size based on the data
		m2.dialog.update(data , "loginDialog");
		// set init state
		this.isLoginInit = true;
	},

	/**
	 * 
	 */
	toggleOpenIdProviders : function() {
		if( m2.$("oidProviders").style.display == "none") {
			m2.$("oidProviders").style.display = "block";
		} else {	
			m2.$("oidProviders").style.display = "none";
		}
		m2.util.Iframe.sendDocumentDimensions(true);

		// hacktastic-ness to prevent negative scrolling of the content.
		m2.$('loginHTMLNode').scrollTop = 0;
	},
    
    /**
     * Selects an Open ID provider using the given url.
     * 
     * @param {Object} url provider url
     * @param {Object} id portion of the url identifying the user
     */
    selectOpenIdProvider : function(url, id) {
        // Set the url.
        var el = m2.$("openId");
        el.value = url;
        
        // Set focus on the field and select the username portion.
        if (id) {
            var start = url.indexOf(id);
            var end = start + id.length;
            
            if (el.setSelectionRange) {
                el.setSelectionRange(start, end);
                el.focus();   
            }  else if (el.createTextRange) {
                var range = el.createTextRange();  
                range.collapse(true);
                range.moveEnd('character',end);
                range.moveStart('character',start); 
                range.select();
            }
        } else {
            el.focus();
        }
    }, 	
		
	/**
	 * Function will submit the login form
	 * @param {DomNode} form  the form we are submitting for login
	 * @scope httpsChild
	
	submitLogin : function(form) {
        $awsn('MQ08MySignIn', m2.widget.user.Login._screen);        
        this.doLogin(m2.util.FormUtil.getValues(form));
	},  */
    
    /**
     * Function will execute the login process using the given data.  Allows login processing without
     * having to submit a form.
     * 
     * @param {Object} data
     */
    doLogin : function(data) {alert('AuthService');
		// Show status message.			
		m2.util.Iframe.sendMessage("loading", {message:"Logging into My Places..."});

		// Check signIn-RememberMe option. String test is to handle old invalid cookie encoding.
		var userPreferenceObj = m2.Cookie.getJsonCookie("USER_PREFERENCE");
		var rme = data.remember;
		if (!userPreferenceObj || (typeof userPreferenceObj == "string")) { userPreferenceObj = { singIn_RememberMe_OID : "no", singOut_NoConfirmBox : "no" }; }
		userPreferenceObj.singIn_RememberMe_AOL = (rme) ? data.loginId : "no";
		this.userPreference = userPreferenceObj;
 
		// Write to cookie
		m2.Cookie.setJsonCookie("USER_PREFERENCE", this.userPreference, 365, "/");
		
		// submit the form to the appropriate service based on the presence of the securid
		var self = this;
        var form = { name : "login", data : data };
		if (!m2.util.isEmptyString(data.securid)) {
			m2.util.DWR.callService(AuthService.securidLogin,self.handleLogin,m2.util.FormUtil.getValuesForDWR(form),this.securidChallenge);
		} else {
			m2.util.DWR.callService(AuthService.login,self.handleLogin,m2.util.FormUtil.getValuesForDWR(form));
		}
    },

	/**
	 * Function will handle the response from the login
	 * @param {Object} response
	 * @scope httpsChild
	 */
	handleLogin : {
		SUCCESS: function(r){
			if (r.data && r.data.token) {
				// call the sns service with the url provided in an iframe.  set an onload handler on the 
				// iframe so that we complete the login process only after sns login is comlete.  this call
				// has to be made from the child https window in order for sns login to be successful.
				
				m2.util.Iframe.sendMessage("hideLoading");
				m2.util.Iframe.sendMessage("loading", {message:"Logging into AOL ..."});
				m2.util.Iframe.create({
					id:"snsFrame",
					src:r.data.clientUrl,
					hidden: true,
					onload:function(){
                		m2.util.Iframe.sendMessage("hideLoading");
                        m2.util.Iframe.sendMessage("loading", {message:"Getting User Data ..."});
                        m2.widget.user.getUser(r.data);
                    }
				});
			}
		},

		CHALLENGE: function(r) {
			// update form to display securid elements
            m2.widget.user.Login.updateScreenName('MQ08MyLoginSecurid');

			m2.$("securidMessage").style.display = "block";
			m2.$("loginMessage").style.display = "none";
			m2.$("securidFields").style.display = "block";
			m2.$("loginFields").style.display = "none";
			
			m2.$("securid").focus();
			m2.widget.user.Login.securidChallenge = r.data.challenge;

			m2.util.Iframe.sendMessage("hideLoading");
			m2.util.Iframe.sendDocumentDimensions(true);
		},
		
		AUTH_ERROR : function(r) {
			m2.widget.user.Login.processFormError(r);
		},		
		
		SERVICE_ERROR : function(r) {
			m2.widget.user.Login.processFormError(r);
		},		
		
		VALIDATION_ERROR: function(r) {
            for (var i = 0; i < r.errors.length; ++i) {
                console.log('error [' + r.errors[i].code + ']: ' + r.errors[i].field);
            }
			m2.widget.user.Login.processFormError(r);
		},

		FAILURE : function(r) {
			// update the parent to the appropriate view
			m2.util.Iframe.sendMessage("loginFailure",r);
		}
	},
	
	
	/**
	 * generic error processing for form errors returned from handle login
	 * @param {Object} r  the repsons object.
	 */
	processFormError : function(r) {
		// mark errors && update the parent to the appropriate view
		m2.util.FormUtil.markErrors(r.errors, m2.$("loginForm"), "aolLoginMessageArea", "error");
		m2.util.Iframe.sendMessage("hideLoading");
		m2.util.Iframe.sendDocumentDimensions(true);
		
		// reset fields
        if (m2.$("loginFields").style.display != "none") {
            // clear the password
    		m2.$("password").value = "";
    		
    		// if the login is empty set focus to that, else to the password.
    		if (m2.$("loginId").value == "") {
    			m2.$("loginId").focus();
    		} else {
    			m2.$("password").focus();
    		}
        } else {
            // clear the securid
            m2.$("securid").value = "";
            m2.$("securid").focus();
        }
	},	

	/**
	 * Handling the generic case of a login failure and displaying a proper error message to the user.
	 * @param {object} r  the response data 
	 */	
	loginFailure : function(r) {
		// show error message and close login dialog
		m2.dialog.loading("Status Code: " + r.statusCode + "<br />Detail Code: " + r.detailCode + "<br />There was a problem during login processing.  Please try again later.");
		m2.dialog.close("loginDialog");
		setTimeout(function() {m2.dialog.hideLoading();},2000);
	},

	/**
	 * 
	 * @param {Object} form
	 */
	submitOpenIdLogin : function(form) {
        $awsn('MQ08MySignIn', m2.widget.user.Login._screen);
        this.doOpenIdLogin(m2.util.FormUtil.getValues(form));
	},
    
    /**
     * 
     * @param {Object} data
     */
    doOpenIdLogin : function(data) {
        // Show status message.
		m2.util.Iframe.sendMessage("loading", {message:"Logging into My Places..."});

		// Check signIn-RememberMe option. String test is to handle old invalid cookie encoding.
		var userPreferenceObj = m2.Cookie.getJsonCookie("USER_PREFERENCE");
		var rme = data.remember;
		if (!userPreferenceObj || (typeof userPreferenceObj == "string")) { userPreferenceObj = { singIn_RememberMe_AOL : "no", singOut_NoConfirmBox : "no" }; }
		userPreferenceObj.singIn_RememberMe_OID = (rme) ? data.loginId : "no";
		this.userPreference = userPreferenceObj;
		
		// Write to cookie
		m2.Cookie.setJsonCookie("USER_PREFERENCE", this.userPreference, 365, "/");
		
		// submit the form
		var self = this;
        var form = { name : "OIDLoginForm", data : data };
		m2.util.DWR.callService(AuthService.openIdLogin,self.handleOpenIdLogin,m2.util.FormUtil.getValuesForDWR(form));
    },
	
	/**
	 * Function will handle the response from the login
	 * @param {Object} response
	 * @scope httpsChild
	 */
	handleOpenIdLogin : {
		SUCCESS: function(r){
            // login always returns a service error
		},

		SERVICE_ERROR : function(r) {
			// auth required - redirect using the return client url
			if (r.data) {
				// dispatch the Open ID login request in the parent frame 
        		m2.util.Iframe.sendMessage('dispatchOpenIdLogin', r.data);
			}
		},		
		
		VALIDATION_ERROR: function(r) {
			// mark errors && update the parent to the appropriate view
			m2.util.FormUtil.markErrors(r.errors, m2.$("OIDLoginForm"), "openIDLoginMessageArea", "error");
			m2.util.Iframe.sendMessage("hideLoading");
			m2.util.Iframe.sendDocumentDimensions(true);
		},

		FAILURE : function(r) {
			// update the parent to the appropriate view
			m2.util.Iframe.sendMessage("loginFailure",r);
		}
	},

	/**
	 * 
	 * @param {Object} data
	 */
	dispatchOpenIdLogin : function(data) {
        // Append hidden form to dialog.
        var dialog = m2.dialog.getDialog("loginDialog");
		var c = document.createElement("div");
    	c.innerHTML = m2.util.widget.template(this.HTML.oidDialog,{
			succUrl	: encodeURIComponent(m2.util.getSecureUrl() + "/login?redirectUrl=" + encodeURIComponent(location.href))
        });
        dialog.contentEl.appendChild(c);
        
        // Convert login query parameters to hidden fields.  Ensures no parameters
        // appear in the post url.  Values are decoded since they will be encoded
        // again when the form is submitted.
        var form = m2.$('oidtabform');
        var parts = data.clientUrl.split('?');
        var url = parts[0];
        form.action = url;
        
        var query = parts[1];
        var params = query.split('&');
        var paramCount = params.length;
        var param;
        
        for (var i = 0; i < paramCount; ++i) {
            param = params[i].split('=');
            m2.util.FormUtil.addHiddenField(form, param[0], decodeURIComponent(param[1]));
        } 
        
        // Submit the form to kick off the login process.
		form.submit();

        // Give the user a clue abot what is happening.
		m2.dialog.close("loginDialog");
	},  
	
    /**
     * Cancels login.
     */        
    cancelLogin : function(actionName) {
        var data = { actionName : actionName, screenName : this._screen };
        m2.util.Iframe.sendMessage("closeLoginDialog", data);
    },
    
    /**
     * Shows the sign up dialog.
     */
    showSignUpDialog : function() {
        var data = { actionName : 'MQ08MySignUp', screenName : this._screen, isCancel : true };
        m2.util.Iframe.sendMessage("showSignUpDialog", data);
    },
    
    /**
     * Calls the dwr service to auto login the user.
     * @scope httpParent
     */
    autoLogin : function() {
        // Attempt to auto login the user if they are not already logged in.
        if (!m2.User.isLoggedIn) {
            var self = this;
            m2.util.DWR.callService(AuthService.autoLogin,self.handleAutoLogin);
        }
    },
    
    /**
    * Handles the response form the auto login method
    * @scope httpParent
    */
    handleAutoLogin : {
        SUCCESS : function(r) {
        },
    
        SERVICE_ERROR : function(r) {
            // Client side login.  Create a javascript include that will write a json object 
            // that calls the function specified.
            var script = document.createElement('script');
            script.type = 'text/javascript';
            script.src = r.data.clientUrl + '&f=json&c=m2.widget.user.Login.handleGetToken';
            document.body.appendChild(script);
        },
    
        FAILURE : function(r) {
            // Do nothin.
        }
    },
    
    /**
    * Handles the response from the handleAutoLogin script file that is generated by the sns system.
    * @param {Object} response
    * @scope httpParent
    */
    handleGetToken : function(response) {
        response = response.response;
        
        if (response.statusCode == 200) {
            var data = {
                token: {
                    token: response.data.token.a,
                    referer: location.href.split('#')[0]
                }
            };
            $a('MQ08MyAutoSignIn', 'v');
            m2.widget.user.getUser(data);
        } else if (response.statusCode == 401) {
        }
    },
    
    /**
     * Closes the login dialog.
     * 
     * @param {Object} data
     */
    closeLoginDialog : function(data) {
        // Check if anything to close.
        if (!m2.dialog.hasDialog("loginDialog")) {
            return;
        } 
        
        // Log action.
        if (data.actionName) {
            $awsn(data.actionName, data.screenName, 'r');
        }
        
        // Close the dialog.
        m2.dialog.close("loginDialog");
        
		// for IE.  the current document loses focus due to the iframe being destroyed.  focus on the first "a" tag of the
		// page to restore the focus.
		//
		// TODO: This should be moved to the dialog.js file to prevent general occurances of iframe dialog's closing
		//       but has not due to one issue.  ex.  If the page is scrolled and we focus on the first "a" tag
		//       as in this solution, the page will jump to the top.  So .. there needs to be a better way to determine 
		//       what element to focus on after an iframe dialog closes.  
		if (m2.isIE) {
			try{
				document.body.getElementsByTagName("input")[0].focus();
			}catch(err){}
		}
    },

	initLogInForm : function () {
		var focusDiv = m2.$("aolLoginTab");
		var focusControl;
		if(focusDiv != null && !focusDiv.disabled && focusDiv.style.visibility != "hidden" && focusDiv.style 
			&& focusDiv.style.display != "none" && focusDiv.type != "hidden") {
            this.updateScreenName('MQ08MyLoginAOL');

			focusControl = m2.$("loginId");
           	if(focusControl) focusControl.focus();
           	var userPreferenceObj = m2.Cookie.getJsonCookie("USER_PREFERENCE");
			if(userPreferenceObj && userPreferenceObj.singIn_RememberMe_AOL && userPreferenceObj.singIn_RememberMe_AOL != "no") {
				focusControl.value = userPreferenceObj.singIn_RememberMe_AOL;
				m2.$("password").focus();
				m2.$("rememberAOL").checked = true;
			}
		} else {
            this.updateScreenName('MQ08MyLoginOpenID');

			focusControl = m2.$("openId");
           	if(focusControl) focusControl.focus();
           	var userPreferenceObj = m2.Cookie.getJsonCookie("USER_PREFERENCE");
			if(userPreferenceObj && userPreferenceObj.singIn_RememberMe_OID && userPreferenceObj.singIn_RememberMe_OID != "no") {
				focusControl.value = userPreferenceObj.singIn_RememberMe_OID;
				m2.$("rememberOID").checked = true;
			}
        }
	},
    
    /**
     * Updates the screen name in both the current and parent contexts.  The screen in the parent context is used
     * when the dialog is closed.
     * 
     * @param {String} screenName screen name
     */        
    updateScreenName : function(screenName) {
        this._screen = screenName;
    },
    
    /**
     * Gets the Omniture screen name.
     */
    getScreenName : function() {
        return this._screen;
    }
};
