/*
 * profile.js
 * Functioanality to implement profile section of Smart Checkout
 * 
 * Profile
 * 	.form 
 * 		Main form
 * 	.mode
 * 		Edit or view. The best check is to test if "mark" input is present
 * 
 * 	.switchModeTo(mode)
 * 		Switches mode to edit or view mode. Default to view mode.
 * 		By default if user is logged in view mode is used with edit button, switching view mode to edit mode
 * 		If customer is not logged in we will show "edit" mode by default.
 * 		
 * 		If edit mode is initiated for unregistered customer, customer must be registered in auto-mode:
 * 			- We will hang listeners /onblur/ and /onfocus/ for each field in profile form 
 * 			If user blured from form element and has not focused on other form element in short time(e.g. 0.5 - 1 second)?
 * 			the form must be sent to server _in case it has no errors_
 * 			- If some error fields detected, do not send form data to server and show error fields somehow
 * 	.checkField()
 * 		If value is incorrect - return false. If correct - true
 * 
 * 	.fieldsValidator - object with rules to check different fields in profile form
 * 
 *  .checkForm()
 * 		Checks form for errors. If form is in view mode(see /switchWiew/) return true
 * 		Else perform all checks and return false if at least one element is incorrect. The easiest way is to check
 * 		if there are any elements with "Required" class set.
 * 	.checkCompleteForm()
 * 		Runs .checkForm() and then indicates errors if some.
 * 	.save()
 * 		Runs .checkCompleteForm, and if success - saves info. Else does nothing
 * 	.editModeHandler()
 * 		Handler, that activates interative functionality accessible via "edit" mode. This is moved to standalone
 * 		method, because "view" mode is inaccessible to newbie/unregistered user.
 *  .updateButtons()
 * 		Updates "Edit" or "Save" controls visibility according to current mode
 * 
 * .checkLogin() 
 * 		Checks login for new user. If login is always registered - show error.
 * 		Else - show password fields
 * 
 * 
 * === Shipping update algo ===
 * 	If fields from list are filled correctly we should silently update userinfo and update shipping methods
 *  So, the basics
 * 		1. No updates will pe performed until all fields are filled okay
 * 		2. If fields are filled okay, we should remember thier checksum(CRC32)
 * 		3. On each field update: if fields are still filled correctly and CRC32 changed - update shipping via
 * 			ShippingMethod.putContent() method
 * 		   If fields are now incorrecd - show error message(please fill bla-bla-bla)	
 * 
 * 
 * */


__Profile = function(){
	
	SmartCheckout.requiredShippingFields; // Update fields. If all are filled - update shipping methods for location
	this.requiredShippingFields = [];
	
	this.zipLiveCheck = false;	// Enables zip code on-type check
	
	this.mode = $_('#OSCPersonalInfoEditMode') ? 'edit' : 'view';
	this.form = $_('#OSCPersonalInfoForm');
	this.container = $_('#OSCPersonalInfoFields');
	this.accountCheckingIndicator = $_('#OSCProfileAccountLoadingIndicator');
	this.loading = $_('#OSCProfileAccountLoadingIndicator2');
	
	this.updateControl = $_('#OSCPersonalInfoUpdateControl');
	this.editControl = $_('#OSCPersonalInfoEditControl');
	this.cancelControl = $_('#OSCPersonalInfoCancelControl');
	
	var self = this;
	this.editControl.attach('click', function(e){;self.switchModeTo('edit'); e.preventDefault(); e.stopPropagation();})
	this.updateControl.attach('click', function(e){self.save(); e.preventDefault(); e.stopPropagation();})
	// Some constants
	this.URLGetEditMode = SmartCheckout.APIURL+'?ax=1&function=get_profile_html&edit_mode=1';
	this.URLGetViewMode = SmartCheckout.APIURL+'?ax=1&function=get_profile_html';
	this.URLCheckRegistername = SmartCheckout.APIURL+'?ax=1&function=check_registername&username=';
	
	// Events cache
	this.ECacheCheckFields = [];
	
	// Hang login check 
	this.checkLoginHandler()
	
	
	this.noStates = {};	
	
	if(this.mode == 'edit')
		this.editModeHandler()
	
	this.$OrderState = false;

}

__Profile.prototype.switchModeTo = function(mode){
	this.updateControl.CSS({display:'none'});	// Hide updateControl
	this.editControl.CSS({display:'none'});	// Hide updateControl
	this.container.loadingBig(1)				// Show "Loading indicator"
	
	var self = this;
	switch(mode){
		case 'edit':
			this.mode = mode;
			$_(this.URLGetEditMode).GET(function(data){
				self.container.innerHTML = data.stdout;	// Put form into container
				self.editModeHandler();
				self.updateButtons()
				self.$OrderState = false;
			})
		break;
		default:
			// Switch to default 'view' mode
			this.mode = mode;
			$_(this.URLGetViewMode).GET(function(data){
				// Replace content with "view" mode
				self.container.innerHTML = data.stdout;
				self.mode = $_('#OSCPersonalInfoEditMode') ? 'edit' : 'view';
				if(self.mode == 'edit'){
					self.editModeHandler();
					self.$OrderState = false;
				}else{
					if($_('#OSCLogin')) $_('#OSCLogin').CSS({display:'none'});
				}
				self.updateButtons();
			})	
		
	}
	
}
__Profile.prototype.editModeHandler = function(){
	var self = this;
	
	if ($_('@ship2diff') && !$_('@ship2diff').checked && $_('#ship_box'))	// If shipping address is activated, show block
		$_('#ship_box').style.display = 'none';
	
	// Detach old checkers if some
	if(!$_.ie && $_(this.ECacheCheckFields).length)	
		$_(this.ECacheCheckFields).detach()

	// Events cache
	this.ECacheCheckFields = [];

	if(XCart.b_RequireStateField && $_('@b_state') && $_('@b_state').tagName == 'INPUT'){
		 $_('@b_state').className = 'Required';
	}
	if($_('@s_state')){
		if(XCart.s_RequireStateField && $_('@s_state') && $_('@s_state').tagName == 'INPUT'){
			 $_('@s_state').className = 'Required';
		}	
	}
	var tmp = [];
	if($_('#s_country')){
		tmp.push($_('#s_country'))
	}
	tmp.push($_('#b_country'))

	$_(tmp).attach('change', function(){
		self.statesHandler(this.id);
	})	
	
	// Because pre-defined classes required are transfered from smarty, update them	
	self.form.$_('.Required').apply(this.mkCheckFieldHandler())
	
	if($_('#s_country'))
		$_('#s_country').onchange = function(){self.checkField( $_('#s_zipcode'))}
	$_('#b_country').onchange = function(){self.checkField($_('#b_zipcode'))}	
	
	//Hang shippingHandler
	var fs = [];
	$_(SmartCheckout.requiredShippingFields).apply(function(el){
		if(el == 'state'){
			if(!$_('@b_state').empty()){ // X-Cart can detach field `state`
				fs.push($_('@b_state'));
			}
			if(!$_('@s_state').empty()){ // X-Cart can detach field `state`
				fs.push($_('@s_state'));
			}		
		}else
			fs.push($_('@b_'+el, '@s_'+el));
	})
	
	if(!fs.empty()){
		self.onShippingChange = fs;
		if(!$_('@ship2diff').empty()){
			$_('@ship2diff').attach('click', function(){
				self.shippingHandler();
			})
		}	
	}
	$_(self.onShippingChange).attach('blur', function(){
		self.shippingHandler();
	})
	
	self.noStates = {};	
	self.statesHandler('b_country');
	if($_('#s_country'))
		self.statesHandler('s_country');
	
	/* Attach error methods */
	if(!this.zipLiveCheck){
		if($_('#b_zipcode')){
			$_('#b_zipcode_error').style.display = 'none';
			$_('#b_zipcode').onblur = function(){
				if($_('#b_zipcode_error').innerHTML) {
					$_('#b_zipcode_error').style.display = '';
				}else{
					$_('#b_zipcode_error').style.display = 'none';
				}
			}
			
		}	
		if($_('#s_zipcode')){
			$_('#s_zipcode_error').style.display = 'none';
			$_('#s_zipcode').onblur = function(){
				if($_('#s_zipcode_error').innerHTML) {
					$_('#s_zipcode_error').style.display = '';
				}else{
					$_('#s_zipcode_error').style.display = 'none';
				}
			}
			
		}	
	}
}

__Profile.prototype.mkCheckFieldHandler = function(){ 
	var self = this;
	return function(element){
		// Run checkfield for element
		self.checkField(element);
		// Attach onkeyup and ochange
		self.ECacheCheckFields[self.ECacheCheckFields.length] = element.attach('keyup', function(){self.checkField(this)})
		self.ECacheCheckFields[self.ECacheCheckFields.length] = element.attach('blur', function(){self.checkField(this)})
		// Hand common X-cart states switch
	}
}

__Profile.prototype.shippingHandler = function(){
	/* Check, if ship2dif is active.
	 * If it is inactive - add b_ to fields	 
	 */
	var self = this;
	var cnFields = [];
	this.requiredShippingFields = [];
	if(this.form.$_('@ship2diff').empty() || !this.form.$_('@ship2diff').VAL()){
		
		$_(SmartCheckout.requiredShippingFields).apply(function(el){
			
			self.requiredShippingFields.push($_('@b_'+el));
			cnFields.push('@b_'+el+'.Required')
		});
	}else{
		// Shipping address is different
		$_(SmartCheckout.requiredShippingFields).apply(function(el){
			self.requiredShippingFields.push($_('@s_'+el));
			cnFields.push('@s_'+el+'.Required')
		})
	}
	this.oldShippingCRC = this.shippingCRC || 0;					// Remember old CRC32
	this.shippingCRC = $_(this.requiredShippingFields).CRC32();	//Calculate new CRC32
	// Now check fields

	$_(this.requiredShippingFields).apply(function(el){
		self.checkField(el);
	})
	
	
	var errState = $_(cnFields);

	if(errState && !errState.empty()){
		// Found error fields, display error dialog
		ShippingMethod.disable();
	}else{
		if(this.oldShippingCRC != this.shippingCRC ){
			// Okay, update shipping methods via putContent
			
			var fs = []
			var flag = ($_('#ship2diff') && $_('#ship2diff').checked);
			if(flag) var pref = 's_';
			else var pref = 'b_';
			
			(['address','address_2','state','country','county','zipcode', 'city']).apply(function(el){
				if($_('@'+pref+el) && !$_('@'+pref+el).empty())
					fs.push($_('@'+pref+el))
								
			});
			if(!ShippingMethod.disabled){
				ShippingMethod.putContent($_(fs).encode2URI());
			}else{
				$_(ShippingMethod.URLGetContent).POST(
					$_(fs).encode2URI(),
					function(data){
						Totals.getContents();
					}
				)
			}
		}
	}
}

__Profile.prototype.updateButtons = function(){
	// Updates buttons according to current mode
	$_(this.cancelControl, this.updateControl).CSS({display: ((this.mode == 'view') ? 'none':'')});
	this.editControl.CSS({display: ((this.mode != 'view') ? 'none':'')});
}


__Profile.prototype.checkField = function(field){
	//if(field.className != 'Required') return true;
	if(this.fieldsValidator[field.name]){
		var state =this.fieldsValidator[field.name](field)
	}else
		var state = !!( (typeof field.VAL == 'undefined') || field.VAL())
	
	field.className = state ? '':'Required'
	return state
}

__Profile.prototype.fieldsValidator =  {
	b_zipcode : function(obj){
		try{
			
			var obj = obj || $_('#b_zipcode')
			if(XCart.b_RequireZipField && !obj.VAL()) throw('')
			var st = RFormValidator.zip (obj.VAL(), $_('#b_country').VAL())
			$_('#b_zipcode_error').innerHTML = '';
			return true;
		}catch(e){
			$_('#b_zipcode_error').innerHTML = e.toString();
		}
	}, 
	s_zipcode: function(obj){
		try{
			if(!$_('@ship2diff').VAL()) return true;
			var obj = obj || $_('#s_zipcode')
			if(XCart.s_RequireZipField && !obj.VAL()) throw('')
			var st = RFormValidator.zip (obj.VAL(), $_('#s_country').VAL())
			$_('#s_zipcode_error').innerHTML = '';
			return true;
		}catch(e){
			$_('#s_zipcode_error').innerHTML = e.toString();
			return false
		}
	}, 
	
	email : function(obj){
		try{
			var st = RFormValidator.email (obj.VAL())
			return true;
		}catch(e){
			return false
		}				
	},
	
	b_county : function(obj){
		try{
			var obj = obj || $_('#b_county')
			if(XCart.b_RequireCountyField && !obj.VAL()) throw('')
			return true;
		}catch(e){
			return false
		}				
	},	
	s_county : function(obj){
		try{
			if(!$_('@ship2diff').VAL()) return true;
			var obj = obj || $_('#s_county')
			if(XCart.s_RequireCountyField && !obj.VAL()) throw('')
			return true;
		}catch(e){
			return false
		}				
	},
		
	passwd1 : function(obj){
		if(!obj.offsetHeight) return true;
		try{
			var st = RFormValidator.passwd(obj.VAL(), $_('@passwd2').VAL())
			$_('.PasswordError').CSS({display:'none'});
			$_('@passwd2').className = '';
			return true;
		}catch(e){
			$_('@passwd2').className = 'Required';
			$_('.PasswordError').CSS({display:''});
		}
	},
	passwd2 : function(obj){
		if(!obj.offsetHeight) return true; // If not visible - not needed
		try{
			var st = RFormValidator.passwd(obj.VAL(), $_('@passwd1').VAL())
			$_('.PasswordError').CSS({display:'none'});
			$_('@passwd1').className = '';
			return true;
		}catch(e){
			$_('@passwd1').className = 'Required';
			$_('.PasswordError').CSS({display:''});
		}
	}	
}
__Profile.prototype.checkCompleteForm = function(){
	var self = this;
	if(!this.checkForm()){
		$_('#OSCPersonalInfoError').CSS({display:''})	// Show error message
		this.focus();		// Scroll to form
		// And hl error fields
		this.form.$_('~input.Required').mutate({backgroundColor:'red'}, {backgroundColor:'#fffddf'},60, function(){setTimeout(function(){self.form.$_('~input.Required').CSS({backgroundColor:''})}, 100)});
		return false;
	}else{
		$_('#OSCPersonalInfoError').CSS({display:'none'})
		return true;
	}
}
__Profile.prototype.checkForm = function(){
	if(this.mode == 'view') return true;
	// Get all text inputs for form and return boolean value
	
	return this.form.$_('~input.Required').empty();
}


__Profile.prototype.save = function(cbf){
	if(!this.checkCompleteForm())
		return false;
	var data = this.form.getData();

	this.container.loadingBig(1) // Set loading
	var self = this;
	$_('cart.php?ax=1&function=update_profile').POST(
		data,
		function(data){
			self.mode = $_('#OSCPersonalInfoEditMode') ? 'edit' : 'view';
			self.switchModeTo();
			Totals.getContents();
			if(typeof cbf == 'function'){
				cbf();
				
			}
			/*$_('#OSCPersonalInfoControl').loading(0)
			console.log(1,data)
			OSCUpdateShippingMethods();
			OSCUpdateTotal();
			OSCUpdatePersonalInfo();*/
			
		})
}


__Profile.prototype.checkLoginHandler = function(){
	var self = this;
	if(!$_('~text@uname')) return true;
	//if($_('#OSCNoAonymousCheckoutAllowed')) return true
		
	
	$_('~text@uname').onkeydown = function(){
		if(self.intId){ clearTimeout(self.intId); self.intId = null;}
		this.oldValue = this.value;
	}
		
	$_('~text@uname').onfocus = function(){
		this.oldValue = this.value;
	}
	
	$_('~text@uname').onkeyup = function(){
		var inp = this;
		if(!self.intId){
			self.intId = setTimeout(function(){
				if(inp.value != inp.oldValue)
				self.checkLogin();
			}, 1500)
		}
	}
	$_('~text@uname').onblur = function(){
		self.checkLogin();
	}
	
}

__Profile.prototype.checkLogin = function(df){
	if(!$_('~text@uname')) return this.registerLogin(0);	// If no login field - all is okay
	if(!$_('~text@uname').value) {this.accountCheckingIndicator.innerHTML = ''; return this.registerLogin(0)};
	this.loading.style.visibility = 'visible'
	this.accountCheckingIndicator.style.display = '';
	var self = this;
	$_(this.URLCheckRegistername+encodeURIComponent($_('~text@uname').value)).GET(function(data){
		self.accountCheckingIndicator.innerHTML = data.stdout ? XCart.Lang.txt_osc_login_is_free : '<span class="Star">'+XCart.Lang.txt_osc_login_is_busy+'</star>';
		self.loading.style.visibility = 'hidden'
		if(!data.stdout){
			$_('~text@uname').mutate({backgroundColor:'red'}, {backgroundColor:'#fffddf'},60, function(){setTimeout(function(){$_('~text@uname').CSS({backgroundColor:''})}, 100)});
			$_('~text@uname').focus();
		}else{
			$_('~text@uname').mutate({backgroundColor:'#0bda51'}, {backgroundColor:'#fffddf'},60, function(){setTimeout(function(){$_('~text@uname').CSS({backgroundColor:''})}, 100)});
		}
		self.registerLogin(data.stdout)
		self.editModeHandler()
		if(df)
			df();
	})
}


__Profile.prototype.registerLogin = function(state){
	if(state){
		// User will register login
		$_('~tr.Password', '.PasswordError').CSS({display:''})
		$_('@passwd1').className = 'Required'
		$_('@passwd2').className = 'Required'
	}else{
		// User will not register login
		$_('~tr.Password', '.PasswordError').CSS({display:'none'})
		$_('@passwd1').className = ''
		$_('@passwd2').className = ''
	}
	
}

__Profile.prototype.$TEST = function(cbf){
	var self = this;
	if(this.mode != 'edit') // If view mode - all okay, return true
		return cbf();
	else{					// Edit mode
		this.save(function(){
			if(self.mode != 'edit'){	// If info is saved okay - run callback function.
				cbf();
			}
		})
	}	
	return this.$OrderState
}

__Profile.prototype.focus = function(){
	window.scrollTo(0, this.form.getXY().y);
}


__Profile.prototype.statesHandler = function(fieldId){
	var self = this;
	var field = $_('#'+fieldId)
	if(!field) return;
	var cType = field.name.substr(0,2);
	var currentStates = {};
	
	if(!this.noStates[cType] || !this.noStates[cType].parentNode){
		var el = $_('#'+cType+'state')
		if(el && (el.tagName.toLowerCase() == 'select' || el.tagName.toLowerCase() == 'input') ){
			currentStates[cType] = $_(el.VAL())
			
			this.noStates[cType] = document.createElement('span');
			this.noStates[cType].id = cType+'state';
			
		}else if($_('#'+cType+'state_container'))
			this.noStates[cType] = $_('#'+cType+'state_container').$_('~span');
		else
			return	
	}

	this.noStates[cType].innerHTML = XCart.Lang.txt_no_states;
	
	var sFieldContainer = $_('#'+cType+'state_container');
	var sField =  $_('#'+cType+'state');
	if(!sFieldContainer) return;
	if(countries[$_(field).VAL()].states){
		// Generate select
		
		if(!countries[$_(field).VAL()].states.empty()){
			var sel = document.createElement('select')
			sel.name = sel.id = cType+'state';
			var states = countries[$_(field).VAL()].states;
			for(var i in states){
				if(parseInt(i)){
					sel.options[sel.options.length] = new Option(states[i].name, states[i].code );
				}
			}
		}else{
			var sel = document.createElement('input');
			sel.type = 'text';
			sel.size = 20
			sel.name = sel.id = cType+'state';
			if(XCart[cType+'RequireStateField'])
				sel.className = 'Required'
		}
		
		$_(sel).VAL(currentStates[cType])
		
		var pn = $_(sFieldContainer)
		while(pn.childNodes.length){
			pn.removeChild(pn.childNodes[0])
		}
		$_(sFieldContainer).appendChild(sel);

		var fs = [];
		$_(SmartCheckout.requiredShippingFields).apply(function(el){
			if(el == 'state'){
				if(!$_('@b_state').empty()){ // X-Cart can detach field `state`
					fs.push($_('@b_state'));
				}
				if(!$_('@s_state').empty()){ // X-Cart can detach field `state`
					fs.push($_('@s_state'));
				}		
			}
		})
		if(fs.length){
			$_(fs).attach('blur', function(){
				self.shippingHandler();
			})
		}
		sel.apply(this.mkCheckFieldHandler())
	}else{	// No states
		if(field.tagName.toLowerCase() != 'select'){
			return;
		}else
			$_(sFieldContainer).replaceChild(this.noStates[cType], sField)
	}
}


__Profile.prototype.checkShip2DiffState = function(){
	if($_('#ship2diff')){
		if(!$_('#ship2diff').checked){
			$_('#ship_box').$_('.Required').apply(function(el){
				el.className = '';
			});
		}else{
			
			$_('#ship_box').style.display = ''
			this.shippingHandler();
		}
	}
}

__Profile.prototype.copyBil2Ship = function(){
	$_(
	'title',
	'first_name',
	'last_name',
	'state',
	'country',
	'county',
	'company',
	'phone',
	'fax',
	"address",
	'address_2',
	'city',
	'zipcode').apply(function(el){
		if(
			!$_('@b_'+el).empty() &&
			!$_('@s_'+el).empty()
		){
			$_('@s_'+el).VAL($_('@b_'+el).VAL(),1 )
		}
	})
	
	$_(
	'state',
	'county').apply(function(el){
		if(
			!$_('@b_'+el).empty() &&
			!$_('@s_'+el).empty()
		){
			$_('@s_'+el).VAL($_('@b_'+el).VAL(),1 )
		}
	})
}

