converterInteface = function (settings) {
	var t = this;
	
	this.converterType = 'money';
	
	$.extend(t, settings);
	
	this.dataCodes = {};
	for(var i in this.data) {
		this.dataCodes[this.data[i].code] = i;
	}

	var i = t.input.fields;
	var o = t.output.fields;

	// get default values
	var input_def = t.input.def, 
		output_def = t.output.def, 
		value_def = t.def || 1;
	
	var uri = window.location.pathname.replace(/\/money\/currency\/?/, '');
	if (uri) {
		uri = uri.split('/');		
		
		var iDef = t.dataCodes[uri[0]];
		if(typeof iDef != 'undefined') {
			input_def = iDef;
		}
		
		var oDef = t.dataCodes[uri[1]];
		if(typeof oDef != 'undefined') {
			output_def = oDef;
		}
		
		if (!isNaN(uri[2]) && uri[2] != '') {
			value_def = uri[2].number();
		}
		
	}
	
	// end: get default values
	
	$.each($(i).add(o), function (i) {
		var initValue = i == 0 ? input_def : output_def;
		t.initAutocomplete(this.format, initValue);
	});
	
	t.updateCurrencyInfoList();
	
	$.each($(i), function () {
		var selector = i[0].field.selector;
		this.field.bind('keyup', t, function(e) {
			var code;
			if (!e) var e = window.event;
			if (e.keyCode) code = e.keyCode;
			else if (e.which) code = e.which;
			
			if(!t.isControlKey(e.type, code)) {
				t.convert(e, t.container.find(selector).index(this));
			}
		});
		
		t.setInputWidth($(this), 0);
		this.field.bind('blur', t, t.changeLocation);
	});
	
	t.container.find('.equal span, .vice-versa').click(function() {
		if(t.input.fields.length == 1) {
			var inCode = t.input.fields[0].format.find('a')[0].href.replace(/^.*#/, '');
			var outCode = t.output.fields[0].format.find('a')[0].href.replace(/^.*#/, '');
			t.output.fields[0].format.find('a')[0].href = '#' + inCode;
			t.input.fields[0].format.find('a')[0].href = '#' + outCode;
			
			t.input.fields[0].field.val(t.output.fields[0].field.val());
			t.convert(null, 0);
		}
	});
	
	if (t.input.buttons) {
		t.input.buttons.add.bind('click', {that: t, io: 'input'}, t.addFields);
		t.input.buttons.remove.bind('click', t, t.removeInputFields);
	}
	
	i[0].field.val(value_def);

	t.resultLink = $('#result-links');
	
	t.container.show();
	
	i[0].field.focus();
	
	t.convert(null, 0);
	
	fixFooterPosition();
}

converterInteface.prototype = {
	
	initAutocomplete: function(format, initValue) {
		var t = this;
		var a = format.find('a');
		var input = format.find('input');
		
		input.autocomplete(
		    window.currencyData,
		    {
			autoFill: false,
			//data: window.currencyData,
			formatItem: function(data) {
				var code = data.code;
				var value = data.nominative;
				if(data.symbol) {
					value += ' ('+data.symbol+', '+data.code+')';
				} else {
					value += ' ('+data.code+')';
				}
				return '<a href="#'+code+'" onclick="return false;">'+value+'</a>';
			},
			formatMatch: function(data) {			    
				var value = data.nominative;
				if(data.symbol) {
					value += ' '+data.symbol;
				}
				value += ' '+data.code;
				return value;
			},
			matchContains: true,
			minChars: 1,
			result: function(event, data, value) {
				a[0].href = '#' + data.code;
				a.text(data.nominative);
				$(this).blur();
				t.convert();
				t.updateCurrencyInfoList();
				return data.nominative;
			},
			scroll: true,
			scrollHeight: 484,
			width: t.autocompleteWidth ? t.autocompleteWidth : null
		});
		
		a.click(function() {
			$(this).hide();
			input.val('');
			input.show();
			input.focus();
		});
		
		input.blur(function() {
			$(this).hide();
			a.show();
		});
		
		if(typeof initValue != 'undefined') {
			a[0].href = '#'+currencyData[initValue].code;
			a.text(currencyData[initValue].nominative);
		}
		
		input.result(function(e, data) {
			$(e.target).hide();
			a.show();
			
			a[0].href = '#' + data.code;
			a.text(data.nominative);
			$(this).blur();
			t.convert();
			t.updateCurrencyInfoList();
			return data.nominative;
		});
		
		input.bind('autocompleteshow', function(e) {		    
			var content = Math.ceil($('#content').offset().top + $('#content').height());
			var results = Math.ceil($('.ui-autocomplete-results:visible').offset().top + $('.ui-autocomplete-results:visible').outerHeight());
			if(results > content) {
				$('#content').height(Math.ceil(results - $('#content').offset().top));
				fixFooterPosition();
			}
		});
		
		input.bind('autocompletehide', function(e) {
			$('#content').css('height', 'auto');
			fixFooterPosition();
		});
		
	},

	addFields: function (e) {
		if (e.target.tagName != 'SPAN') { return; }
		var that = e.data.that;
		var io = e.data.io;

		var f = that[io].fields;

		if (f.length > 7) { return; }

		var oldField = $(this).parent().parent();

		oldField.append('<' + $(this).parent()[0].tagName + '></' + $(this).parent()[0].tagName + '>');

		var newField = oldField.children('li:last');
		$(this).parent().children().each(function (){
			newField.append($(this).clone(!$(this).is('.currency')));
		});

		f.push({
			field: newField.children(f[0].field[0].tagName),
			format: newField.children('.currency')
		});
		that.initAutocomplete(f[f.length - 1].format);
		
		var newInput = f[f.length - 1].field;
		newInput.val() ? newInput.val(0) : newInput.html('&nbsp;');
		that.setInputWidth(newInput, 0);

		if (that[io].buttons && f.length > 1) {
			oldField.find('.remove').removeClass('hidden');
		}

		oldField.parent().addClass('show');

		that.setSelectorValue(f[f.length - 1].format, io); //next value?

		oldField.addClass('multiple');

		var addButtons = that.input.container.find('div.add');
		addButtons.removeClass('last');
		$(addButtons.get(addButtons.size() - 1)).addClass('last');

		if (f.length == 8) {
			that[io].container.children('li:last').children('div.add').addClass('hidden');
		}
		
		if(f.length > 1) {
			$('.vice-versa').hide();
		}

		that.resultLink.hide();
		that.updateCurrencyInfoList();
		
		fixFooterPosition();
	},

	removeInputFields: function(e) {
		var that = e.data;
		var c = $(that.input.container);
		var index = that.input.container.children().index($(this).parent());
		var newField = that.input.fields;

		var f = that.input.fields;
		f.splice(index, 1);
		if (f.length == 1) {
			that.input.container.removeClass('multiple');
			$(this).parent().parent().parent().removeClass('show');
			if (that.input.buttons) {
				c.find('.remove').addClass('hidden');
			}
			
			that.resultLink.show();
			
			$('.vice-versa').show();
		}
		
		$(this).parent().remove();

		var addButtons = that.input.container.find('div.add');
		addButtons.removeClass('last hidden');
		$(addButtons.get(addButtons.size() - 1)).addClass('last');
		
		that.updateCurrencyInfoList();
		that.convert();
		
		fixFooterPosition();
	},

	setSelectorValue: function (selector, f) {
		var t = this;

		if (this.priorityFormats) {
			var all_data = [];
			for(var i=0; i<t.data.length; i++) {
				all_data[i] = t.data[i].code;
			}

			var arr = [];   //exist formats
			for (var i = 0; i < this.input.fields.length - 1; i++) {
				arr[i] = this.input.fields[i].format.find('a')[0].href.replace(/^.*#/, '');
			}
			
			var arr = $.grep(t.priorityFormats, function (n) {
				return $.inArray(n, arr) == -1;
			});
			
			var value = arr.length ? $.inArray(arr[0], all_data) : this.input.fields.length-1;
			
			var a = $(selector).find('a');
			var input = $(selector).find('input');
			a[0].href = '#'+t.data[value].code;
			a.text(t.data[value].plural);
			
			if($.browser.msie && $.browser.versionX == 8) {
				$(selector).parents('.converter .input').next('span').css('zoom', '1');
			}
		}
	},

	convert: function(e, activeEl) {
		var t = e && e.data ? e.data : this;
		if (e && e.type) {
			if (t.lastEventType == 'keyup' && e.type == 'keypress') { 
				t.lastEventType = e.type;
				return;
			}
			t.lastEventType = e.type;
		}

		var f_i = t.input.fields;
		var f_o = t.output.fields; 

		var iInputs = 0;
		var firstInputFormat = t.dataCodes[f_i[0].format.find('a')[0].href.replace(/^.*#/, '')];
		
		for (var i = 0, c = f_i.length; i < c; i++) {
			var iField = f_i[i].field;
			var useComma = iField.val().indexOf(',') > -1;
			var iVal = iField.val().replace(',', '.').replace(/ /g, ''); // do string like float

			if (isNaN(iVal)) {
				iField.addClass('i_error');
				iInputs = false;
			} else {
				iField.removeClass('i_error');
			}
			
			var input_id = t.input.fields[i].format.find('a')[0].href.replace(/^.*#/, '');
			var valAbs = Math.abs(iVal); // delete minuses?
			if (valAbs.toString().indexOf('.') > -1) { // define case for current f_i currency
				var numdecl = 'genitive';
			} else { 
				var numdecl = (
					valAbs % 10 == 1 && valAbs % 100 != 11 
						? 'nominative'
						: valAbs % 10 >= 2 && valAbs % 10 <= 4 && (valAbs % 100 < 10 || valAbs % 100 >= 20) 
							? 'genitive'
							: 'plural'
				);
			}
			
			var input_text = t.data[t.dataCodes[input_id]][numdecl];
			
			f_i[i].format.find('a').text(input_text);
			//
			// t.sType				- always money
			// f_i[i].format.val() 	- index in select	
			// firstInputFormat 	- index of first currency 					
			// iVal 				- input value
			//
			var formatIndex = t.dataCodes[f_i[i].format.find('a')[0].href.replace(/^.*#/, '')];
			var val = t.converter.convert(t.converterType, formatIndex, firstInputFormat, Number(iVal)); 
			iInputs += val; // summation of currencies

			var spacerCount = iField.val().match(/ /g);

			iVal = t.lastInputValue = t.separateDigits(iVal);

				var spacerCount2 = iVal.match(/ /g);
				spacerCount = (spacerCount2 ? iVal.match(/ /g).length : 0) - (spacerCount ? spacerCount.length : 0);

			var elem = iField[0];
			var caretPos = 0;
			
			if (elem.createTextRange) {
				var r = document.selection.createRange().duplicate()
				r.moveEnd('character', elem.value.length)
				if (r.text == '') {
					caretPos = elem.value.length + spacerCount;
				} else {
					caretPos = elem.value.lastIndexOf(r.text) + spacerCount;
				}
			} else if (elem.selectionStart) {
				caretPos = elem.selectionStart  + spacerCount;
			}
			
			iField.val(useComma ? iVal.replace('.', ',') : iVal);
			
			if(typeof activeEl != 'undefined' && activeEl == i) {
				if(elem.selectionStart) {
					if(iField.val().charAt(caretPos-1) == ' ' && e && e.keyCode == 8) {
						elem.setSelectionRange(caretPos-1, caretPos-1);
					} else {
						elem.setSelectionRange(caretPos, caretPos);
					}
				} else if (elem.createTextRange) {
					var range = elem.createTextRange();
					if(iField.val().charAt(caretPos-1) == ' ' && e && e.keyCode == 8) {
						range.move('character', caretPos-1);
					} else {
						range.move('character', caretPos);
					}
					range.select();
				} else {
					elem.focus();
				}
				t.setInputWidth(iField, 0);
			}
		}
		
		if (iInputs || (!isNaN(iInputs) && t.converter.data[t.converterType].special)) {
			for (var i = 0, c = f_o.length; i < c; i++) {
				for(var j=0; j<t.data.length; j++) {
					if(t.data[j].code == f_o[i].format.find('a')[0].href.replace(/^.*#/, '')) {
						var formatIndex = j;
					}
				}
				var val = t.converter.convert(t.converterType, firstInputFormat, formatIndex, iInputs);
				var iNzero = (Math.abs(val) < 1 && val != 0) ? t.calcNzero(val) : 0;
				val = t.expandExponential(val).toString();

				// if (t.lastValue == val) {								// enable later
				// f_o[i].field.removeClass('o_error');
				// return;
				// }

				var iPointIndex = val.indexOf('.');

				if (Math.abs(val) < 1) {
					if (val.substr(iNzero + 1).length > 7) {
						val = t.expandExponential(t.roundValue(val, 5, iNzero)).toString();
					}
				} else {
					if (val.substr(iPointIndex + 1) / val.substr(0, iPointIndex) < Math.pow(10, -5) || val.substr(iPointIndex + 1).length > 7) {
						val = t.expandExponential(t.roundValue(val, 5, iNzero)).toString();
						iPointIndex = val.indexOf('.');
					}
				}

				var bNegative = val < 0;
				t.minus = bNegative ? '-' : '';
				
				val = t.expandExponential(Math.abs(val)).toString();
				
				var iSubZero = (val.substr(0, iPointIndex) > 0) ? t.calcNzero('0.' + val.substr(iPointIndex + 1)) - 1 : 0;

				if (iPointIndex > -1) {
					if (t.slider && (val.length - (iPointIndex + 1) >= t.round)) {
						if (val > 1) {
							if (iSubZero) {
								var n = t.round + (iPointIndex - 1) + 1 + (t.slider ? iSubZero : 0); //no slider for money (fixed round);
							} else {
								var n = t.round + iPointIndex;
							}
						} else {
							var n = Math.max(1, Math.min(t.round, val.substr(iNzero + 1).length));
						}
					} else {
						if (t.slider) {
							var n = val.length - 1 - iNzero;
						} else {
							var n = t.round + ((val > 1) ? val.substr(0, iPointIndex).length : val.substr(0, iPointIndex - 1).length);
						}
					}
				} else {
					var n = 0;
				}

				val = t.separateDigits(val);
				var val_full = t.lastValue = val;
				if (n > 0) {
					val = t.separateDigits(t.expandExponential(Number(val.replace(/ /g, '')).toPrecision(n)));
				}
				iPointIndex = val.indexOf('.');

				var output_id = t.output.fields[i].format.find('a')[0].href.replace(/^.*#/, '');
				var valAbs = Math.abs(val);
				if (iPointIndex > -1) {
					var numdecl = 'genitive';
				} else { 
					var numdecl = (valAbs % 10 == 1 && valAbs % 100 != 11 ? 'nominative' : valAbs % 10 >= 2 && valAbs % 10 <= 4 && (valAbs % 100 < 10 || valAbs % 100 >= 20) ? 'genitive' : 'plural');
				}

				f_o[i].field.val(t.minus + val.replace('.', ','));
				t.setInputWidth(f_o[i].field);

				f_o[i].format.find('a').text(t.data[t.dataCodes[output_id]][numdecl]);
				
				f_o[i].field.removeClass('o_error');

				// result link update
				if (f_i.length == 1) {
					if (t.resultLink[0]) {
						var slocation = t.sLocation = input_id + '/' + output_id + '/' + iInputs,
							full_location = 'http://' + window.BaseServer + '/money/currency/' + slocation;
                        
						t.resultLink.find('#result-link-url').val(full_location);
                        $('#result-link-code').val('<a href="' + full_location + '">' + iInputs.toString().replace('.', ',') + ' ' + input_text + ' ' + s('in') + ' ' + t.data[t.dataCodes[output_id]].prepositional + '</a>');	
                        t.resultLink.show();
						fixFooterPosition();
					}
				}
			}
		} else {
			for (var i = 0, c = f_o.length; i < c; i++) {
				if (iInputs != 0) {
					f_o[i].field.addClass('o_error');
				} else {
					var input_id = t.input.fields[i].format.find('a')[0].href.replace(/^.*#/, '');
					f_i[i].format.find('a').text(t.data[t.dataCodes[input_id]].plural);
					
					var output_id = t.output.fields[i].format.find('a')[0].href.replace(/^.*#/, '');
					f_o[i].format.find('a').text(t.data[t.dataCodes[output_id]].plural);

					f_o[i].field.val(0);
					f_o[i].field.removeClass('o_error');
				}
				if (t.resultLink[0]) 
				{
					t.sLocation = '';
					t.resultLink.hide();
				}
			}
		}
	},

	changeLocation: function (e) { /*empty*/ },

	separateDigits: function (v) {
		var i = v.indexOf('.');
		if (i > -1) {
			return i > 4 ? v.replace(/(\d{1,3}(?=(\d{3})+\.\d))/g,'\$1 ') : v;
		} else {
			return v.length > 4 ? v.replace(/(\d{1,3}(?=(\d{3})+$))/g,'\$1 ') : v;
		}
	},

	roundValue: function (v, round, iNzero) {
		var iRound = round > 0 ? round : 0;

		var iPrec = Math.pow(10, iRound);
		
		if (Math.abs(v) < 1 && iNzero) {
			var iZeroK = Math.pow(10, iNzero + iRound - 1);
			
			v = Math.round(v * iZeroK) / iZeroK;

			if (iNzero > 6) {
				v = this.expandExponential(v);
			}
		} else {
			v = Math.round(v * iPrec) / iPrec;
			if (v.toString().length > 18) {
				v = this.expandExponential(v);
			}
		}
		return v;
	},

	calcNzero: function (v) {
		return Math.abs(Math.floor(Math.log(Math.abs(v)) / Math.log(10)));
	},

	expandExponential: function (n) {
		return n.toString().replace(/^([+-])?(\d+).?(\d*)[eE]([-+]?\d+)$/, function(x, s, n, f, c){
			var l = +c < 0, i = n.length + +c, x = (l ? n : f).length,
			c = ((c = Math.abs(c)) >= x ? c - x + l : 0),
			z = (new Array(c + 1)).join('0'), r = n + f;
			return (s || '') + (l ? r = z + r : r += z).substr(0, i += l ? z.length : 0) + (i < r.length ? '.' + r.substr(i) : '');
		});
	},
	
	isControlKey: function(eventType, code) {
		var controlKeys = [];
		switch(eventType) {
			case 'keyup':
				controlKeys = [16, 35, 36, 37, 38, 39, 40];
				break;
			default:
				break;
		}
		
		for(var i in controlKeys) {
			if(controlKeys[i] == code) return true;
		}
		
		return false;
	},
	
	setInputWidth: function(input, add) {
		if(typeof add == 'undefined') {
			add = '';
		}
		var span = input.next(':first');
		span.text(input.val()+add);
		input.width(span.width());
	},
	
	updateCurrencyInfoList: function() {
		if(this.history) {
            var history = this.history.empty();
            
            var arr = [];
            this.container.find('.currency a').each(function(){
                
                var code = $(this).attr('href').replace('#', '');
                if(code != 'RUB' && $.inArray(code, arr) == -1) {
                    arr.push(code);
                    history.append('<li><a href="/money/'+code+'">'+s('rate info')+' '+code+'</a></li>');
                }
                
            });
            
            if (!arr.length) {
                history.hide();
            } else {
                history.show();
            }
        }
	}
}
