/*
 *  ====================================================================
 *    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.functions;

import java.util.Calendar;

import org.apache.poi.ss.formula.eval.BlankEval;
import org.apache.poi.ss.formula.eval.ErrorEval;
import org.apache.poi.ss.formula.eval.EvaluationException;
import org.apache.poi.ss.formula.eval.MissingArgEval;
import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.OperandResolver;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.usermodel.DateUtil;


/**
 * Implementation for the Excel function WEEKDAY
 *
 * @author Thies Wellpott
 */
public final class WeekdayFunc implements Function {
//or:  extends Var1or2ArgFunction {

	public static final Function instance = new WeekdayFunc();

	private WeekdayFunc() {
		// no fields to initialise
	}

	/* for Var1or2ArgFunction:
	@Override
	public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) {
	}

	@Override
	public ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0, ValueEval arg1) {
	}
	*/


	/**
	 * Perform WEEKDAY(date, returnOption) function.
	 * Note: Parameter texts are from German EXCEL-2010 help.
	 * Parameters in args[]:
	 *  args[0] serialDate
	 * EXCEL-date value
	 * Standardmaessig ist der 1. Januar 1900 die fortlaufende Zahl 1 und
	 * der 1. Januar 2008 die fortlaufende Zahl 39.448, da dieser Tag nach 39.448 Tagen
	 * auf den 01.01.1900 folgt.
	 * @return Option (optional)
	 * Bestimmt den Rueckgabewert:
		1	oder nicht angegeben Zahl 1 (Sonntag) bis 7 (Samstag). Verhaelt sich wie fruehere Microsoft Excel-Versionen.
		2	Zahl 1 (Montag) bis 7 (Sonntag).
		3	Zahl 0 (Montag) bis 6 (Sonntag).
		11	Die Zahlen 1 (Montag) bis 7 (Sonntag)
		12	Die Zahlen 1 (Dienstag) bis 7 (Montag)
		13	Die Zahlen 1 (Mittwoch) bis 7 (Dienstag)
		14	Die Zahlen 1 (Donnerstag) bis 7 (Mittwoch)
		15	Die Zahlen 1 (Freitag) bis 7 (Donnerstag)
		16	Die Zahlen 1 (Samstag) bis 7 (Freitag)
		17	Die Zahlen 1 (Sonntag) bis 7 (Samstag)
	 */
	public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) {
		try {
			if (args.length < 1  ||  args.length > 2) {
				return ErrorEval.VALUE_INVALID;
			}

			// extract first parameter
			ValueEval serialDateVE = OperandResolver.getSingleValue(args[0], srcRowIndex, srcColumnIndex);
			double serialDate = OperandResolver.coerceValueToDouble(serialDateVE);
			if (!DateUtil.isValidExcelDate(serialDate)) {
				return ErrorEval.NUM_ERROR;						// EXCEL uses this and no VALUE_ERROR
			}
			Calendar date = DateUtil.getJavaCalendar(serialDate, false);		// (XXX 1904-windowing not respected)
			int weekday = date.get(Calendar.DAY_OF_WEEK);		// => sunday = 1, monday = 2, ..., saturday = 7

			// extract second parameter
			int returnOption = 1;					// default value
			if (args.length == 2) {
				ValueEval ve = OperandResolver.getSingleValue(args[1], srcRowIndex, srcColumnIndex);
				if (ve == MissingArgEval.instance  ||  ve == BlankEval.instance) {
					return ErrorEval.NUM_ERROR;		// EXCEL uses this and no VALUE_ERROR
				}
				returnOption = OperandResolver.coerceValueToInt(ve);
				if (returnOption == 2) {
					returnOption = 11;				// both mean the same
				}
			} // if

			// perform calculation
			double result;
			if (returnOption == 1) {
				result = weekday;
			// value 2 is handled above (as value 11)
			} else if (returnOption == 3) {
				result = (weekday + 6 - 1) % 7;
			} else if (returnOption >= 11  &&  returnOption <= 17) {
				// rotate in the value range 1 to 7
				result = (weekday + 6 - (returnOption - 10)) % 7 + 1.;
			} else {
				// EXCEL uses this and no VALUE_ERROR
				return ErrorEval.NUM_ERROR;
			}

			return new NumberEval(result);
		} catch (EvaluationException e) {
			return e.getErrorEval();
		}
	} // evaluate()

}
