/*
 * Axelor Business Solutions
 *
 * Copyright (C) 2018 Axelor (<http://axelor.com>).
 *
 * This program is free software: you can redistribute it and/or  modify
 * it under the terms of the GNU Affero General Public License, version 3,
 * as published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
package com.axelor.apps.base.service;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.temporal.ChronoUnit;

import com.axelor.apps.base.db.Duration;
import com.axelor.apps.base.db.repo.DurationRepository;
import com.axelor.i18n.I18n;
import com.google.common.base.Preconditions;
import com.google.inject.Singleton;

@Singleton
public class DurationServiceImpl implements DurationService  {

	private static final BigDecimal DAYS_IN_MONTH = BigDecimal.valueOf(30);

	@Override
	public LocalDate computeDuration(Duration duration, LocalDate date) {
		if(duration == null) { return date; }
		switch (duration.getTypeSelect()) {
			case DurationRepository.TYPE_MONTH:
				return date.plusMonths(duration.getValue());
			case DurationRepository.TYPE_DAY:
				return date.plusDays(duration.getValue());
			default:
				return date;
		}
	}

	@Override
	public BigDecimal computeRatio(LocalDate start, LocalDate end, Duration duration) {
		Preconditions.checkNotNull(start,I18n.get("You can't compute a" +
				" duration ratio without start date."));
		Preconditions.checkNotNull(end, I18n.get("You can't compute a" +
				" duration ratio without end date."));
		if (duration == null) { return BigDecimal.ONE; }
		end = end.plus(1, ChronoUnit.DAYS);

		if (duration.getTypeSelect() == DurationRepository.TYPE_MONTH) {
			long months = ChronoUnit.MONTHS.between(start, end);
			LocalDate theoryEnd = start.plusMonths(months);
			long restDays = ChronoUnit.DAYS.between(theoryEnd, end);
			long daysInMonth = ChronoUnit.DAYS.between(theoryEnd, theoryEnd.plusMonths(1));
			return BigDecimal.valueOf(months)
					.add(BigDecimal.valueOf(restDays).divide(BigDecimal.valueOf(daysInMonth), MathContext.DECIMAL32))
					.divide(BigDecimal.valueOf(duration.getValue()), MathContext.DECIMAL32);
		} else {
		    long restDays = ChronoUnit.DAYS.between(start, end);
		    return BigDecimal.valueOf(restDays).divide(BigDecimal.valueOf(duration.getValue()), MathContext.DECIMAL32);
		}
	}

}

@@ -1175,82 +1175,8 @@
  %7B%0A%0A
-%09private static final BigDecimal DAYS_IN_MONTH = BigDecimal.valueOf(30);%0A%0A
 %09@Ov
@@ -2207,37 +2207,49 @@
 nth = ChronoUnit
-.DAYS
+%0A%09%09%09%09%09.DAYS%0A%09%09%09%09%09
 .between(theoryE
@@ -2345,32 +2345,40 @@
 alueOf(restDays)
+%0A%09%09%09%09%09%09%09
 .divide(BigDecim
@@ -2401,17 +2401,26 @@
 nMonth),
- 
+%0A%09%09%09%09%09%09%09%09%09
 MathCont
@@ -2480,33 +2480,40 @@
 ion.getValue()),
- 
+%0A%09%09%09%09%09%09%09
 MathContext.DECI
@@ -2533,20 +2533,17 @@
 lse %7B%0A%09%09
-    
+%09
 long res
@@ -2593,12 +2593,9 @@
 ;%0A%09%09
-    
+%09
 retu
@@ -2625,16 +2625,22 @@
 estDays)
+%0A%09%09%09%09%09
 .divide(
@@ -2679,17 +2679,24 @@
 alue()),
- 
+%0A%09%09%09%09%09%09%09
 MathCont

refactor DurationServiceImpl