/* ====================================================================
   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>
 */
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() + "'");
	}
}
