/* ====================================================================
   Licensed to the Apache Software Foundation (ASF) under one or more
   contributor license agreements.  See the NOTICE file distributed with
   this work for additional information regarding copyright ownership.
   The ASF licenses this file to You under the Apache License, Version 2.0
   (the "License"); you may not use this file except in compliance with
   the License.  You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
==================================================================== */

package org.apache.poi.ss.formula.atp;

import java.util.Calendar;

import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.util.Internal;
import org.apache.poi.util.LocaleUtil;


/**
 * Internal calculation methods for Excel 'Analysis ToolPak' function YEARFRAC()<br>
 *
 * Algorithm inspired by www.dwheeler.com/yearfrac
 */
@Internal
final class YearFracCalculator {
	private static final int MS_PER_HOUR = 60 * 60 * 1000;
	private static final int MS_PER_DAY = 24 * MS_PER_HOUR;
	private static final int DAYS_PER_NORMAL_YEAR = 365;
	private static final int DAYS_PER_LEAP_YEAR = DAYS_PER_NORMAL_YEAR + 1;

	/** the length of normal long months i.e. 31 */
	private static final int LONG_MONTH_LEN = 31;
	/** the length of normal short months i.e. 30 */
	private static final int SHORT_MONTH_LEN = 30;
	private static final int SHORT_FEB_LEN = 28;
	private static final int LONG_FEB_LEN = SHORT_FEB_LEN + 1;

	private YearFracCalculator() {
		// no instances of this class
	}


	public static double calculate(double pStartDateVal, double pEndDateVal, int basis) throws EvaluationException {

		if (basis < 0 || basis >= 5) {
			// if basis is invalid the result is #NUM!
			throw new EvaluationException(ErrorEval.NUM_ERROR);
		}

		// common logic for all bases

		// truncate day values
		int startDateVal = (int) Math.floor(pStartDateVal);
		int endDateVal = (int) Math.floor(pEndDateVal);
		if (startDateVal == endDateVal) {
			// when dates are equal, result is zero
			return 0;
		}
		// swap start and end if out of order
		if (startDateVal > endDateVal) {
			int temp = startDateVal;
			startDateVal = endDateVal;
			endDateVal = temp;
		}

		switch (basis) {
			case 0: return basis0(startDateVal, endDateVal);
			case 1: return basis1(startDateVal, endDateVal);
			case 2: return basis2(startDateVal, endDateVal);
			case 3: return basis3(startDateVal, endDateVal);
			case 4: return basis4(startDateVal, endDateVal);
		}
		throw new IllegalStateException("cannot happen");
	}


	/**
	 * @param startDateVal assumed to be less than or equal to endDateVal
	 * @param endDateVal assumed to be greater than or equal to startDateVal
	 */
	private static double basis0(int startDateVal, int endDateVal) {
		SimpleDate startDate = createDate(startDateVal);
		SimpleDate endDate = createDate(endDateVal);
		int date1day = startDate.day;
		int date2day = endDate.day;

		// basis zero has funny adjustments to the day-of-month fields when at end-of-month
		if (date1day == LONG_MONTH_LEN && date2day == LONG_MONTH_LEN) {
			date1day = SHORT_MONTH_LEN;
			date2day = SHORT_MONTH_LEN;
		} else if (date1day == LONG_MONTH_LEN) {
			date1day = SHORT_MONTH_LEN;
		} else if (date1day == SHORT_MONTH_LEN && date2day == LONG_MONTH_LEN) {
			date2day = SHORT_MONTH_LEN;
			// Note: If date2day==31, it STAYS 31 if date1day < 30.
			// Special fixes for February:
		} else if (startDate.month == 2 && isLastDayOfMonth(startDate)) {
			// Note - these assignments deliberately set Feb 30 date.
			date1day = SHORT_MONTH_LEN;
			if (endDate.month == 2 && isLastDayOfMonth(endDate)) {
				// only adjusted when first date is last day in Feb
				date2day = SHORT_MONTH_LEN;
			}
		}
		return calculateAdjusted(startDate, endDate, date1day, date2day);
	}
	/**
	 * @param startDateVal assumed to be less than or equal to endDateVal
	 * @param endDateVal assumed to be greater than or equal to startDateVal
	 */
	private static double basis1(int startDateVal, int endDateVal) {
		assert(startDateVal <= endDateVal);
		SimpleDate startDate = createDate(startDateVal);
		SimpleDate endDate = createDate(endDateVal);
		double yearLength;
		if (isGreaterThanOneYear(startDate, endDate)) {
			yearLength = averageYearLength(startDate.year, endDate.year);
			assert(yearLength > 0);
		} else if (shouldCountFeb29(startDate, endDate)) {
			yearLength = DAYS_PER_LEAP_YEAR;
		} else {
			yearLength = DAYS_PER_NORMAL_YEAR;
		}
		return dateDiff(startDate.tsMilliseconds, endDate.tsMilliseconds) / yearLength;
	}

	/**
	 * @param startDateVal assumed to be less than or equal to endDateVal
	 * @param endDateVal assumed to be greater than or equal to startDateVal
	 */
	private static double basis2(int startDateVal, int endDateVal) {
		return (endDateVal - startDateVal) / 360.0;
	}
	/**
	 * @param startDateVal assumed to be less than or equal to endDateVal
	 * @param endDateVal assumed to be greater than or equal to startDateVal
	 */
	private static double basis3(double startDateVal, double endDateVal) {
		return (endDateVal - startDateVal) / 365.0;
	}
	/**
	 * @param startDateVal assumed to be less than or equal to endDateVal
	 * @param endDateVal assumed to be greater than or equal to startDateVal
	 */
	private static double basis4(int startDateVal, int endDateVal) {
		SimpleDate startDate = createDate(startDateVal);
		SimpleDate endDate = createDate(endDateVal);
		int date1day = startDate.day;
		int date2day = endDate.day;


		// basis four has funny adjustments to the day-of-month fields when at end-of-month
		if (date1day == LONG_MONTH_LEN) {
			date1day = SHORT_MONTH_LEN;
		}
		if (date2day == LONG_MONTH_LEN) {
			date2day = SHORT_MONTH_LEN;
		}
		// Note - no adjustments for end of Feb
		return calculateAdjusted(startDate, endDate, date1day, date2day);
	}


	private static double calculateAdjusted(SimpleDate startDate, SimpleDate endDate, int date1day,
			int date2day) {
		double dayCount
			= (endDate.year - startDate.year) * 360.0
			+ (endDate.month - startDate.month) * (double)SHORT_MONTH_LEN
			+ (date2day - date1day) * 1.0;
		return dayCount / 360;
	}

	private static boolean isLastDayOfMonth(SimpleDate date) {
		if (date.day < SHORT_FEB_LEN) {
			return false;
		}
		return date.day == getLastDayOfMonth(date);
	}

	private static int getLastDayOfMonth(SimpleDate date) {
		switch (date.month) {
			case 1:
			case 3:
			case 5:
			case 7:
			case 8:
			case 10:
			case 12:
				return LONG_MONTH_LEN;
			case 4:
			case 6:
			case 9:
			case 11:
				return SHORT_MONTH_LEN;
		}
		if (isLeapYear(date.year)) {
			return LONG_FEB_LEN;
		}
		return SHORT_FEB_LEN;
	}

	/**
	 * Assumes dates are no more than 1 year apart.
	 * @return <code>true</code> if dates both within a leap year, or span a period including Feb 29
	 */
	private static boolean shouldCountFeb29(SimpleDate start, SimpleDate end) {
		if (isLeapYear(start.year)) {
	        if (start.year == end.year) {
	            // note - dates may not actually span Feb-29, but it gets counted anyway in this case
	            return true;
	        }

	        switch (start.month) {
				case SimpleDate.JANUARY:
				case SimpleDate.FEBRUARY:
					return true;
			}
			return false;
		}

		if (isLeapYear(end.year)) {
			switch (end.month) {
				case SimpleDate.JANUARY:
					return false;
				case SimpleDate.FEBRUARY:
					break;
				default:
					return true;
			}
			return end.day == LONG_FEB_LEN;
		}
		return false;
	}

	/**
	 * @return the whole number of days between the two time-stamps.  Both time-stamps are
	 * assumed to represent 12:00 midnight on the respective day.
	 */
	private static int dateDiff(long startDateMS, long endDateMS) {
		long msDiff = endDateMS - startDateMS;

		// some extra checks to make sure we don't hide some other bug with the rounding
		int remainderHours = (int) ((msDiff % MS_PER_DAY) / MS_PER_HOUR);
		switch (remainderHours) {
			case 0:  // normal case
				break;
			case 1:  // transition from normal time to daylight savings adjusted
			case 23: // transition from daylight savings adjusted to normal time
				// Unexpected since we are using UTC_TIME_ZONE
			default:
				throw new RuntimeException("Unexpected date diff between " + startDateMS + " and " + endDateMS);

		}
		return (int) (0.5 + ((double)msDiff / MS_PER_DAY));
	}

	private static double averageYearLength(int startYear, int endYear) {
		assert(startYear <= endYear);
		int dayCount = 0;
		for (int i=startYear; i<=endYear; i++) {
			dayCount += isLeapYear(i) ? DAYS_PER_LEAP_YEAR : DAYS_PER_NORMAL_YEAR;
		}
		double numberOfYears = endYear-startYear+1.;
		return dayCount / numberOfYears;
	}

	private static boolean isLeapYear(int i) {
		// leap years are always divisible by 4
		if (i % 4 != 0) {
			return false;
		}
		// each 4th century is a leap year
		if (i % 400 == 0) {
			return true;
		}
		// all other centuries are *not* leap years
		return i % 100 != 0;
	}

	private static boolean isGreaterThanOneYear(SimpleDate start, SimpleDate end) {
		assert(start.year <= end.year);
		if (start.year == end.year) {
			return false;
		}
		if (start.year + 1 != end.year) {
			return true;
		}

		if (start.month > end.month) {
			return false;
		}
		if (start.month < end.month) {
			return true;
		}

		return start.day < end.day;
	}

	private static SimpleDate createDate(int dayCount) {
	    /* use UTC time-zone to avoid daylight savings issues */
		Calendar cal = LocaleUtil.getLocaleCalendar(LocaleUtil.TIMEZONE_UTC);
		DateUtil.setCalendar(cal, dayCount, 0, false, false);
		return new SimpleDate(cal);
	}

	private static final class SimpleDate {

		public static final int JANUARY = 1;
		public static final int FEBRUARY = 2;

		public final int year;
		/** 1-based month */
		public final int month;
		/** day of month */
		public final int day;
		/** milliseconds since 1970 */
		public final long tsMilliseconds;

		public SimpleDate(Calendar cal) {
			year = cal.get(Calendar.YEAR);
			month = cal.get(Calendar.MONTH) + 1;
			day = cal.get(Calendar.DAY_OF_MONTH);
			tsMilliseconds = cal.getTimeInMillis();
		}
	}
}
