Xeon.Core.namespace('Calculator');

Calculator.Deposit = function() {
	this.id = null;
	this.description = '';
	this.rates = [];
	this.options = [];
	
	this.getDepositPercent = function(oDepositParams)
	{
		var aPeriods = this.rates.pct[oDepositParams.currencyType];
		for(var i = 0; i < aPeriods.length; i++) {
			if (oDepositParams.amountOnDeposit >= aPeriods[i].min && 
				oDepositParams.amountOnDeposit < aPeriods[i].max) {
				var aDays = aPeriods[i].days;
				for (var j = 0; j < aDays.length; j++) {
					if (oDepositParams.depositPeriod >= aDays[j].min && 
						oDepositParams.depositPeriod <= aDays[j].max) {					
						return aDays[j].percent
					}
				}
				break;
			}
		}
		return 0;
	};
	
	this.datesToEndPeriod = function(startPeriodDate, endPeriodDate)
	{
		return Math.ceil(((endPeriodDate - startPeriodDate) / (24 * 60 * 60 * 1000)).toFixed(1));
	};
	
	this.endDateOfQuarter = function(date)
	{
		 var quart = Math.floor(date.getMonth() / 3) + 1;
		 return new Date(date.getFullYear(), (quart*3), 0, 0, 0, 0, 0);
		  
	};
	
	this.normalizeDate = function(date)
	{
		date.setHours(0,0,0,0);
		return date;
	};
	
	this.daysInPeriods = function(startDate, endDate, periodType)
	{
		startDate = this.normalizeDate(startDate);
		endDate = this.normalizeDate(endDate);
		
		var periods = [];
		
		switch (periodType) {
		case 'monthly':
			var currentMonth = new Date(startDate);
			var nextMonth = new Date(startDate);
			nextMonth.setMonth(nextMonth.getMonth() + 1)
			nextMonth.setDate(1);
			while(currentMonth <= endDate) {
				var ed = new Date(nextMonth);
				ed.setDate(ed.getDate() - 1);
				periods.push({
					start: new Date(currentMonth),
					end: ed,
					days: this.datesToEndPeriod(currentMonth, nextMonth)
				});
				currentMonth.setMonth(currentMonth.getMonth() + 1);
				currentMonth.setDate(1);
				nextMonth.setMonth(nextMonth.getMonth() + 1);				
			}
			if (periods.length) {
				currentMonth.setMonth(currentMonth.getMonth() - 1); 
				var ed = new Date(endDate);
				ed.setDate(ed.getDate() - 1);
				periods[periods.length-1] = {
					start: new Date(currentMonth),
					end: ed,						
					days: endDate.getDate() - 1
				};
			}
			break;
		case 'quarterly':
			var currentQuart = new Date(startDate);
			var nextQuart = this.endDateOfQuarter(startDate);
			nextQuart.setDate(nextQuart.getDate() + 1);			
			while(currentQuart <= endDate) {
				var ec = new Date(nextQuart);
				ec.setDate(ec.getDate() - 1);
				periods.push({
					start: new Date(currentQuart),
					end: ec,
					days: this.datesToEndPeriod(currentQuart, nextQuart)
				});
				currentQuart = new Date(nextQuart);
				currentQuart.setDate(1);
				nextQuart = this.endDateOfQuarter(currentQuart);
				nextQuart.setDate(nextQuart.getDate() + 1);			
			}
			var ec = new Date(endDate);
			ec.setDate(ec.getDate() - 1);				
			if (periods.length) {
				currentQuart.setMonth(currentQuart.getMonth() - 3);
				periods[periods.length-1] = {
					start: currentQuart,
					end: ec,
					days: this.datesToEndPeriod(currentQuart, endDate)
				};
			} else {
				periods.push({
					start: startDate,
					end: ec,
					days: this.datesToEndPeriod(startDate, endDate)
				});
			}
			break;
		case 'end':
			var ed = new Date(endDate);
			ed.setDate(ed.getDate() - 1);			
			periods.push({
				start: startDate,
				end: ed,
				days: this.datesToEndPeriod(startDate, endDate)
			});
			break;
		}
		
		return periods; 
	};
	
	this.getSummPct = function(oDepositParams, depositPct)
	{
		if (typeof depositPct == "undefined" || depositPct == null) {
			depositPct = this.getDepositPercent(oDepositParams);
		}
		var beginDate = oDepositParams.openDate;
		var endDate = new Date(beginDate);
		endDate.setDate(endDate.getDate() + oDepositParams.depositPeriod);
		var aDaysInPeriod = this.daysInPeriods(beginDate, endDate, this.options.pay_period);
		var S = oDepositParams.amountOnDeposit;
		var pctByPeriod = 0;
		var summPct = 0;
		for(var i = 0; i < aDaysInPeriod.length; i++) {
			pctByPeriod = S * depositPct / 365 * aDaysInPeriod[i].days; //Проценты за период
			S = S + this.options.cap_of_pct * pctByPeriod;                       //При условии капитализации процентов
			summPct += pctByPeriod;
		}

		return summPct;
	};
	
	this.getPctOfHit = function(oDepositParams)
	{
		var pct = 0;
		var pctHit = 0.25;

		pct += pctHit * (this.options.pay_period == oDepositParams.paymentOfPct);
		pct += pctHit * (this.options.cap_of_pct == oDepositParams.capOfPct);
		pct += pctHit * (this.options.write_down == oDepositParams.writeDown);
		pct += pctHit * (this.options.resupply == oDepositParams.resupply);

		return pct;
	};
	
	this.getPaySchedule = function(oDepositParams, oTaxationParams)
	{
		var depositPct = this.getDepositPercent(oDepositParams);
		var beginDate = oDepositParams.openDate;
		var endDate = new Date(beginDate);
		endDate.setDate(endDate.getDate() + oDepositParams.depositPeriod);
		var aDaysInPeriod = this.daysInPeriods(beginDate, endDate, this.options.pay_period);
		
		var amtRemains = oDepositParams.amountOnDeposit; // сумма остатка		
		var pctByPeriod = 0;                    		 // начисленные проценты
		var payPctByPeriod = 0;                			 // выплаченные проценты
		var payTax = 0;									 // уплаченный налог
		var taxBase = 0;								 // Налогооблагаемая база
		var excessRate = (depositPct - (oTaxationParams.refinancingRate + 0.05)).toFixed(4); // ставка превышения	
		excessRate = excessRate > 0 ? excessRate : 0;

		var res = new DataOfPeriod();
		
		for(var i = 0; i < aDaysInPeriod.length; i++) {
            pctByPeriod = amtRemains * depositPct / 365.0 * (aDaysInPeriod[i].days);
            taxBase = amtRemains * excessRate / 365.0 * (aDaysInPeriod[i].days);
            payTax = taxBase * oTaxationParams.taxRate;
            payPctByPeriod = pctByPeriod - payTax;
            amtRemains += payPctByPeriod * this.options.cap_of_pct; 
            
            var period = new DataOfPeriod();
            period.periodBeginDate = aDaysInPeriod[i].start;
            period.periodEndDate = aDaysInPeriod[i].end;
            period.calc.pctByPeriod = pctByPeriod;
            period.calc.taxBase = taxBase;
            period.calc.payTax = payTax;
            period.calc.payPctByPeriod = payPctByPeriod;
            period.calc.amtRemains = amtRemains;
            res.addPeriod(period);
		}
		return res;
	}
}
