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

import org.apache.poi.util.LittleEndianInput;
import org.apache.poi.util.LittleEndianOutput;
import org.apache.poi.util.StringUtil;

/**
 * To support Constant Values (2.5.7) as required by the CRN record.
 * This class is also used for two dimensional arrays which are encoded by 
 * EXTERNALNAME (5.39) records and Array tokens.<p>
 * 
 * @author Josh Micich
 */
public final class ConstantValueParser {
	// note - these (non-combinable) enum values are sparse.
	private static final int TYPE_EMPTY = 0;
	private static final int TYPE_NUMBER = 1;
	private static final int TYPE_STRING = 2;
	private static final int TYPE_BOOLEAN = 4; 
	private static final int TYPE_ERROR_CODE = 16; // TODO - update OOO document to include this value
	
	private static final int TRUE_ENCODING = 1; 
	private static final int FALSE_ENCODING = 0;
	
	// TODO - is this the best way to represent 'EMPTY'?
	private static final Object EMPTY_REPRESENTATION = null;

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

	public static Object[] parse(LittleEndianInput in, int nValues) {
		Object[] result = new Object[nValues];
		for (int i = 0; i < result.length; i++) {
			result[i] = readAConstantValue(in);
		}
		return result;
	}

	private static Object readAConstantValue(LittleEndianInput in) {
		byte grbit = in.readByte();
		switch(grbit) {
			case TYPE_EMPTY:
				in.readLong(); // 8 byte 'not used' field
				return EMPTY_REPRESENTATION; 
			case TYPE_NUMBER:
				return Double.valueOf(in.readDouble());
			case TYPE_STRING:
				return StringUtil.readUnicodeString(in);
			case TYPE_BOOLEAN:
				return readBoolean(in);
			case TYPE_ERROR_CODE:
				int errCode = in.readUShort();
				// next 6 bytes are unused
				in.readUShort();
				in.readInt();
				return ErrorConstant.valueOf(errCode);
		}
		throw new RuntimeException("Unknown grbit value (" + grbit + ")");
	}

	private static Object readBoolean(LittleEndianInput in) {
		byte val = (byte)in.readLong(); // 7 bytes 'not used'
		switch(val) {
			case FALSE_ENCODING:
				return Boolean.FALSE;
			case TRUE_ENCODING:
				return Boolean.TRUE;
		}
		// Don't tolerate unusual boolean encoded values (unless it becomes evident that they occur)
		throw new RuntimeException("unexpected boolean encoding (" + val + ")");
	}

	public static int getEncodedSize(Object[] values) {
		// start with one byte 'type' code for each value
		int result = values.length * 1;
		for (Object value : values) {
			result += getEncodedSize(value);
		}
		return result;
	}

	/**
	 * @return encoded size without the 'type' code byte
	 */
	private static int getEncodedSize(Object object) {
		if(object == EMPTY_REPRESENTATION) {
			return 8;
		}
		Class<?> cls = object.getClass();
		
		if(cls == Boolean.class || cls == Double.class || cls == ErrorConstant.class) {
			return 8;
		}
		String strVal = (String)object;
		return StringUtil.getEncodedSize(strVal);
	}

	public static void encode(LittleEndianOutput out, Object[] values) {
		for (Object value : values) {
			encodeSingleValue(out, value);
		}
	}

	private static void encodeSingleValue(LittleEndianOutput out, Object value) {
		if (value == EMPTY_REPRESENTATION) {
			out.writeByte(TYPE_EMPTY);
			out.writeLong(0L);
			return;
		}
		if (value instanceof Boolean) {
			Boolean bVal = ((Boolean)value);
			out.writeByte(TYPE_BOOLEAN);
			long longVal = bVal.booleanValue() ? 1L : 0L;
			out.writeLong(longVal);
			return;
		}
		if (value instanceof Double) {
			Double dVal = (Double) value;
			out.writeByte(TYPE_NUMBER);
			out.writeDouble(dVal.doubleValue());
			return;
		}
		if (value instanceof String) {
			String val = (String) value;
			out.writeByte(TYPE_STRING);
			StringUtil.writeUnicodeString(out, val);
			return;
		}
		if (value instanceof ErrorConstant) {
			ErrorConstant ecVal = (ErrorConstant) value;
			out.writeByte(TYPE_ERROR_CODE);
			long longVal = ecVal.getErrorCode();
			out.writeLong(longVal);
			return;
		}

		throw new IllegalStateException("Unexpected value type (" + value.getClass().getName() + "'");
	}
}
