Calculator = Class.create({
	initialize: function(frm) {
		this.frm = $(frm);
		this.rate = 0;
		this.reserve = 0;
		this.comiss = {manual: 0, automatic: 0};
		this.discount = 0;
		this.moduleFrom = new Module(this);
		this.moduleFrom.bindFrom();
		this.moduleTo = new Module(this);
		this.moduleTo.bindTo();
		this.manager = new Manager(this.frm);
		this.manager.append('calc').append('from').append('to');
		$(this.frm.elements.sum_in).observe('blur', this.calculateOut.bindAsEventListener(this));
		$(this.frm.elements.sum_in).observe('x:change', this.calculateOut.bindAsEventListener(this));
		$(this.frm.elements.sum_out).observe('blur', this.calculateIn.bindAsEventListener(this));
		$(this.frm.elements.sum_out).observe('x:change', this.calculateIn.bindAsEventListener(this));
		this.frm.observe('x:done', this.toggleComplete.bindAsEventListener(this));
		$('variant-manual').observe('click', this.updateForm.bindAsEventListener(this));
		$('variant-automatic').observe('click', this.updateForm.bindAsEventListener(this));
		$('reserve').observe('click', this.grabAll.bindAsEventListener(this));
		this.setModule('from', this.getModule('from').value);
		this.setModule('to', this.getModule('to').value);
		this.checkDiscount();
		this.toggleDirection();
	},
	getModule: function(dir) {
		return this.frm.elements[dir+'_id'];
	},
	setModule: function(dir, mod) {
		$('calculator-'+dir+'-'+this.getModule(dir).value).removeClassName('act');
		this.getModule(dir).value = mod;
		$('calculator-'+dir+'-'+mod).addClassName('act');
		return this;
	},
	calcOnCreate: function(req) {
		valid.getHandler('sum_in').clear();
		valid.getHandler('sum_out').clear();
		this.frm.prototip.hide();
	},
	calcOnSuccess: function(req) {
		var json = req.responseJSON;
		this.rate = json.rate;
		this.reserve = json.reserve;
		this.comiss.manual = json.comiss_man;
		this.comiss.automatic = json.comiss_auto;
		if (!json.status) {
			this.reserve = 0;
		}
		this.moduleFrom.update(json.fee['in'], json.limit['in']);
		this.moduleTo.update(json.fee['out'], json.limit['out']);
		var to_max = Math.min(json.to_max, this.reserve);
		var to_min = Math.min(json.to_min, to_max);
		valid.getHandler('sum_in').bind('range', {min: json.from_min, max: json.from_max, hint: 'Допустимая сумма: '+json.from_min+' - '+json.from_max});
		valid.getHandler('sum_out').bind('range', {min: to_min, max: to_max, hint: 'Допустимая сумма: '+String(to_min).toFloat(2)+' - '+String(to_max).toFloat(2)});
		var minSum = Math.max(json.from_min, this.outToIn(json.to_min));
		this.changeSum(minSum, 'in');
		this.manager.done('calc');
	},
	calcOnFailure: function(req) {
		this.rate = 0;
		this.reserve = 0;
		this.comiss.manual = 0;
		this.comiss.automatic = 0;
		this.updateForm();
	},
	formOnCreate: function(req, dir) {
		$('calculator-'+dir).update('<img src="/res/ajax/loader-col.gif" alt="Загрузка" />');
	},
	formOnFailure: function(req, dir) {
		$('calculator-'+dir).update('<img src="/res/ajax/error.png" alt="Ошибка" class="png" />');
	},
	formOnSuccess: function(req, dir) {
		$('calculator-'+dir).update(req.responseText);
		$('calculator-'+dir).setStyle({
			height: (req.responseText == '')?'0':'auto'
		});
		this.manager.done(dir);
		if (dir == 'from') {
			this.moduleFrom.bindFromPs();
		} else {
			this.moduleTo.bindToPs();
		}
	},
	toggleDirection: function() {
		this.manager.reset();
		new Ajax.Request('/ajax/calc.php', {
			parameters: this.frm.serialize(),
			onCreate: this.calcOnCreate.bindAsEventListener(this),
			onSuccess: this.calcOnSuccess.bindAsEventListener(this),
			onFailure: this.calcOnFailure.bindAsEventListener(this)
		});
		new Ajax.Request('/ajax/form.php', {
			parameters: {module_id: this.getModule('from').value, dir: 'from'},
			onCreate: this.formOnCreate.bindAsEventListener(this, 'from'),
			onFailure: this.formOnFailure.bindAsEventListener(this, 'from'),
			onSuccess: this.formOnSuccess.bindAsEventListener(this, 'from')
		});
		new Ajax.Request('/ajax/form.php', {
			parameters: {module_id: this.getModule('to').value, dir: 'to'},
			onCreate: this.formOnCreate.bindAsEventListener(this, 'to'),
			onFailure: this.formOnFailure.bindAsEventListener(this, 'to'),
			onSuccess: this.formOnSuccess.bindAsEventListener(this, 'to')
		});
	},
	toggleComplete: function() {
		this.updateForm();
		this.moduleFrom.calculateSumInPs();
		this.moduleTo.calculateSumOutPs();
	},
	discountOnSuccess: function(req) {
		this.discount = req.responseText;
		this.updateForm();
	},
	checkDiscount: function() {
		new Ajax.Request('/ajax/discount.php', {
			onSuccess: this.discountOnSuccess.bindAsEventListener(this)
		});
	},
	updateForm: function() {
		$('reserve').update(this.reserve+' '+this.getModule('to').value);
		$('comiss').update(this.getComiss());
		this.calculateOut();
	},
	getComiss: function() {
		var vrn = $('variant-automatic').checked?'automatic':'manual';
		var cms = this.comiss[vrn];
		if (cms > 0) {
			cms = (cms * (100 - this.discount)).round() / 100;
		}
		return cms;
	},
	changeSum: function(sum, dir, caller) {
		this.frm.elements['sum_'+dir].value = String(sum).toFloat(2);
		if (caller) {
			$(this.frm.elements['sum_'+dir]).fire('x:change', {caller: caller});
		}
	},
	inToOut: function(sum) {
		var sum_in = Number(sum) - this.moduleFrom.calculateComiss('store', 'in', sum);
		var sum_out = sum_in * this.rate * (100 - this.getComiss()) / 100;
		sum_out = this.moduleTo.getAvailableSum('store', sum_out);
		return sum_out;
	},
	outToIn: function(sum) {
		var sum_out = Number(sum) + this.moduleTo.calculateComiss('store', 'out', sum);
		var sum_in = 0;
		if (this.rate != 0) {
			sum_in = sum_out / this.rate / (100 - this.getComiss()) * 100;
		}
		sum_in = this.moduleFrom.getOutgoingSum('store', sum_in);
		return sum_in;
	},
	calculateOut: function(e) {
		var el = this.frm.elements.sum_in;
		el.value = el.value.toFloat(2);
		var sum_out = this.inToOut(el.value);
		this.changeSum(sum_out, 'out', (e && e.memo && e.memo.caller == 'calcin')?null:'calcout');
	},
	calculateIn: function(e) {
		var el = this.frm.elements.sum_out;
		el.value = el.value.toFloat(2);
		var sum_in = this.outToIn(el.value);
		this.changeSum(sum_in, 'in', 'calcin');
	},
	grabAll: function() {
		this.changeSum(this.reserve, 'out', 'graball');
	}
});
jsLoader.load('/res/string.js');
