package edu.uci.ics.asterix.om.util;

import java.util.List;

import edu.uci.ics.asterix.common.exceptions.AsterixException;
import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AInt16SerializerDeserializer;
import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AOrderedListSerializerDeserializer;
import edu.uci.ics.asterix.dataflow.data.nontagged.serde.ARecordSerializerDeserializer;
import edu.uci.ics.asterix.dataflow.data.nontagged.serde.AUnorderedListSerializerDeserializer;
import edu.uci.ics.asterix.om.types.ARecordType;
import edu.uci.ics.asterix.om.types.ATypeTag;
import edu.uci.ics.asterix.om.types.AUnionType;
import edu.uci.ics.asterix.om.types.BuiltinType;
import edu.uci.ics.asterix.om.types.EnumDeserializer;
import edu.uci.ics.asterix.om.types.IAType;
import edu.uci.ics.hyracks.algebricks.core.api.exceptions.NotImplementedException;

public final class NonTaggedFormatUtil {

    public static final int OPTIONAL_TYPE_INDEX_IN_UNION_LIST = 1;

    public static final boolean isFixedSizedCollection(IAType type) {
        switch (type.getTypeTag()) {
            case STRING:
            case RECORD:
            case ORDEREDLIST:
            case UNORDEREDLIST:
            case ANY:
                return false;
            case UNION:
                if (!NonTaggedFormatUtil.isOptionalField((AUnionType) type))
                    return false;
                else
                    return isFixedSizedCollection(((AUnionType) type).getUnionList().get(
                            OPTIONAL_TYPE_INDEX_IN_UNION_LIST));
            default:
                return true;
        }
    }

    public static final boolean hasNullableField(ARecordType recType) {
        IAType type;
        List<IAType> unionList;
        for (int i = 0; i < recType.getFieldTypes().length; i++) {
            type = recType.getFieldTypes()[i];
            if (type != null) {
                if (type.getTypeTag() == ATypeTag.NULL)
                    return true;
                if (type.getTypeTag() == ATypeTag.UNION) { // union
                    unionList = ((AUnionType) type).getUnionList();
                    for (int j = 0; j < unionList.size(); j++)
                        if (unionList.get(j).getTypeTag() == ATypeTag.NULL)
                            return true;

                }
            }
        }
        return false;
    }

    public static boolean isOptionalField(AUnionType unionType) {
        if (unionType.getUnionList().size() == 2)
            if (unionType.getUnionList().get(0).getTypeTag() == ATypeTag.NULL)
                return true;
        return false;
    }

    public static int getFieldValueLength(byte[] serNonTaggedAObject, int offset, ATypeTag typeTag, boolean tagged)
            throws AsterixException {
        switch (typeTag) {
            case ANY:
                ATypeTag tag = EnumDeserializer.ATYPETAGDESERIALIZER.deserialize(serNonTaggedAObject[offset]);
                if (tag == ATypeTag.ANY) {
                    throw new AsterixException("Field value has type tag ANY, but it should have a concrete type.");
                }
                return getFieldValueLength(serNonTaggedAObject, offset, tag, true) + 1;
            case NULL:
                return 0;
            case BOOLEAN:
            case INT8:
                return 1;
            case INT16:
                return 2;
            case INT32:
            case FLOAT:
            case DATE:
                return 4;
            case TIME:
                return 4;
            case INT64:
            case DOUBLE:
            case DATETIME:
            case DURATION:
                return 8;
            case POINT:
                return 16;
            case POINT3D:
            case CIRCLE:
                return 24;
            case LINE:
            case RECTANGLE:
                return 32;
            case POLYGON:
                if (tagged)
                    return AInt16SerializerDeserializer.getShort(serNonTaggedAObject, offset + 1) * 16 + 2;
                else
                    return AInt16SerializerDeserializer.getShort(serNonTaggedAObject, offset) * 16 + 2;
            case STRING:
                if (tagged)
                    return AInt16SerializerDeserializer.getUnsignedShort(serNonTaggedAObject, offset + 1) + 2;
                else
                    return AInt16SerializerDeserializer.getUnsignedShort(serNonTaggedAObject, offset) + 2;
            case RECORD:
                if (tagged)
                    return ARecordSerializerDeserializer.getRecordLength(serNonTaggedAObject, offset + 1) - 1;
                else
                    return ARecordSerializerDeserializer.getRecordLength(serNonTaggedAObject, offset) - 1;
            case ORDEREDLIST:
                if (tagged)
                    return AOrderedListSerializerDeserializer.getOrderedListLength(serNonTaggedAObject, offset + 1) - 1;
                else
                    return AOrderedListSerializerDeserializer.getOrderedListLength(serNonTaggedAObject, offset) - 1;
            case UNORDEREDLIST:
                if (tagged)
                    return AUnorderedListSerializerDeserializer.getUnorderedListLength(serNonTaggedAObject, offset + 1) - 1;
                else
                    return AUnorderedListSerializerDeserializer.getUnorderedListLength(serNonTaggedAObject, offset) - 1;
            default:
                throw new NotImplementedException("No getLength implemented for a value of this type " + typeTag + " .");
        }
    }

    public static int getNumDimensions(ATypeTag typeTag) {
        switch (typeTag) {
            case POINT:
            case LINE:
            case POLYGON:
            case CIRCLE:
                return 2;
            case POINT3D:
                return 3;
            default:
                throw new NotImplementedException("getNumDimensions is not implemented for this type " + typeTag + " .");
        }
    }

    public static IAType getNestedSpatialType(ATypeTag typeTag) {
        switch (typeTag) {
            case POINT:
            case LINE:
            case POLYGON:
            case CIRCLE:
                return BuiltinType.ADOUBLE;
            default:
                throw new NotImplementedException(typeTag + " is not a supported spatial data type.");
        }
    }
}
