/* ELEval.java

	Purpose:
		
	Description:
		
	History:
		Apr 6, 2010 11:55:15 AM, Created by henrichen

Copyright (C) 2010 Potix Corporation. All Rights Reserved.

*/

package org.zkoss.zssex.formula;

import java.util.Date;

import org.zkoss.poi.ss.formula.eval.BoolEval;
import org.zkoss.poi.ss.formula.eval.ErrorEval;
import org.zkoss.poi.ss.formula.eval.EvaluationException;
import org.zkoss.poi.ss.formula.eval.NumberEval;
import org.zkoss.poi.ss.formula.eval.OperandResolver;
import org.zkoss.poi.ss.formula.eval.StringEval;
import org.zkoss.poi.ss.formula.eval.ValueEval;
import org.zkoss.poi.ss.formula.functions.FreeRefFunction;
import org.zkoss.poi.ss.formula.OperationEvaluationContext;
import org.zkoss.xel.Expressions;
import org.zkoss.xel.XelContext;
import org.zkoss.zssex.formula.ELEval;

/**
 * A function that do EL evaluation.
 * @author henrichen
 *
 */
public class ELEval implements FreeRefFunction {

	public static final FreeRefFunction instance = new ELEval();
	public static final String NAME = "ELEVAL";

	private ELEval() {
		// enforce singleton
	}
	
	@Override
	public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
		if (args.length != 1) {
			return ErrorEval.NAME_INVALID;
		}
		try {
			final ValueEval ve = OperandResolver.getSingleValue(args[0], ec.getRowIndex(), ec.getColumnIndex());
			final String expression = OperandResolver.coerceValueToString(ve);
			final XelContext ctx = XelContextHolder.getXelContext();
			final Object obj = Expressions.evaluate(ctx, expression, (Class<?>) ctx.getAttribute("zkoss.zss.CellType"));
			if (obj == null) {
				return ErrorEval.NAME_INVALID;
			}
			if (obj instanceof String) {
				return new StringEval((String)obj);
			} else if (obj instanceof Number) {
				return new NumberEval(((Number)obj).doubleValue());
			} else if (obj instanceof Boolean) {
				return BoolEval.valueOf(((Boolean)obj).booleanValue());
			} else if (obj instanceof Date) {
				return new NumberEval(javaMillSecondToExcelDate(((Date)obj).getTime()));
			}
		} catch (EvaluationException e) {
			return e.getErrorEval();
		}

		//ZSS-562: evaluate to an unsupported type of value, shall return #VALUE!
		return ErrorEval.VALUE_INVALID;
	}

	private double javaMillSecondToExcelDate(long date) {
		return date / (1000 * 60 * 60 * 24);
	}
}
