/*
 * Copyright 2009-2010 by The Regents of the University of California
 * Licensed 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 from
 * 
 *     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 edu.uci.ics.asterix.metadata.entitytupletranslators;

import java.io.ByteArrayInputStream;
import java.io.DataInput;
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.IOException;
import java.rmi.RemoteException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import edu.uci.ics.asterix.builders.IARecordBuilder;
import edu.uci.ics.asterix.builders.OrderedListBuilder;
import edu.uci.ics.asterix.builders.RecordBuilder;
import edu.uci.ics.asterix.formats.nontagged.AqlSerializerDeserializerProvider;
import edu.uci.ics.asterix.metadata.MetadataException;
import edu.uci.ics.asterix.metadata.MetadataNode;
import edu.uci.ics.asterix.metadata.bootstrap.MetadataPrimaryIndexes;
import edu.uci.ics.asterix.metadata.bootstrap.MetadataRecordTypes;
import edu.uci.ics.asterix.metadata.entities.AsterixBuiltinTypeMap;
import edu.uci.ics.asterix.metadata.entities.Datatype;
import edu.uci.ics.asterix.om.base.ABoolean;
import edu.uci.ics.asterix.om.base.AOrderedList;
import edu.uci.ics.asterix.om.base.ARecord;
import edu.uci.ics.asterix.om.base.AString;
import edu.uci.ics.asterix.om.base.IACursor;
import edu.uci.ics.asterix.om.types.AOrderedListType;
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.AUnorderedListType;
import edu.uci.ics.asterix.om.types.AbstractCollectionType;
import edu.uci.ics.asterix.om.types.BuiltinType;
import edu.uci.ics.asterix.om.types.IAType;
import edu.uci.ics.hyracks.algebricks.common.exceptions.NotImplementedException;
import edu.uci.ics.hyracks.api.dataflow.value.ISerializerDeserializer;
import edu.uci.ics.hyracks.api.exceptions.HyracksDataException;
import edu.uci.ics.hyracks.data.std.util.ArrayBackedValueStorage;
import edu.uci.ics.hyracks.dataflow.common.data.accessors.ITupleReference;
import edu.uci.ics.hyracks.storage.am.btree.exceptions.BTreeDuplicateKeyException;

/**
 * Translates a Datatype metadata entity to an ITupleReference and vice versa.
 */
public class DatatypeTupleTranslator extends AbstractTupleTranslator<Datatype> {
    // Field indexes of serialized Dataset in a tuple.
    // First key field.
    public static final int DATATYPE_DATAVERSENAME_TUPLE_FIELD_INDEX = 0;
    // Second key field.
    public static final int DATATYPE_DATATYPE_TUPLE_FIELD_INDEX = 1;
    // Payload field containing serialized Datatype.
    public static final int DATATYPE_PAYLOAD_TUPLE_FIELD_INDEX = 2;

    public enum DerivedTypeTag {
        ENUM,
        RECORD,
        UNION,
        UNORDEREDLIST,
        ORDEREDLIST
    };

    @SuppressWarnings("unchecked")
    private ISerializerDeserializer<ARecord> recordSerDes = AqlSerializerDeserializerProvider.INSTANCE
            .getSerializerDeserializer(MetadataRecordTypes.DATATYPE_RECORDTYPE);
    private final MetadataNode metadataNode;
    private final long txnId;

    public DatatypeTupleTranslator(long txnId, MetadataNode metadataNode, boolean getTuple) {
        super(getTuple, MetadataPrimaryIndexes.DATATYPE_DATASET.getFieldCount());
        this.txnId = txnId;
        this.metadataNode = metadataNode;
    }

    @Override
    public Datatype getMetadataEntytiFromTuple(ITupleReference frameTuple) throws MetadataException, IOException {
        byte[] serRecord = frameTuple.getFieldData(DATATYPE_PAYLOAD_TUPLE_FIELD_INDEX);
        int recordStartOffset = frameTuple.getFieldStart(DATATYPE_PAYLOAD_TUPLE_FIELD_INDEX);
        int recordLength = frameTuple.getFieldLength(DATATYPE_PAYLOAD_TUPLE_FIELD_INDEX);
        ByteArrayInputStream stream = new ByteArrayInputStream(serRecord, recordStartOffset, recordLength);
        DataInput in = new DataInputStream(stream);
        ARecord datatypeRecord = (ARecord) recordSerDes.deserialize(in);
        return createDataTypeFromARecord(datatypeRecord);
    }

    private Datatype createDataTypeFromARecord(ARecord datatypeRecord) throws MetadataException {
        String dataverseName = ((AString) datatypeRecord
                .getValueByPos(MetadataRecordTypes.DATATYPE_ARECORD_DATAVERSENAME_FIELD_INDEX)).getStringValue();
        String datatypeName = ((AString) datatypeRecord
                .getValueByPos(MetadataRecordTypes.DATATYPE_ARECORD_DATATYPENAME_FIELD_INDEX)).getStringValue();
        IAType type = AsterixBuiltinTypeMap.getBuiltinTypes().get(datatypeName);
        if (type == null) {
            // Derived Type
            ARecord derivedTypeRecord = (ARecord) datatypeRecord
                    .getValueByPos(MetadataRecordTypes.DATATYPE_ARECORD_DERIVED_FIELD_INDEX);
            DerivedTypeTag tag = DerivedTypeTag.valueOf(((AString) derivedTypeRecord
                    .getValueByPos(MetadataRecordTypes.DERIVEDTYPE_ARECORD_TAG_FIELD_INDEX)).getStringValue());
            boolean isAnonymous = ((ABoolean) derivedTypeRecord
                    .getValueByPos(MetadataRecordTypes.DERIVEDTYPE_ARECORD_ISANONYMOUS_FIELD_INDEX)).getBoolean();
            switch (tag) {
                case ENUM:
                    throw new NotImplementedException("Enum type");
                case RECORD: {
                    ARecord recordType = (ARecord) derivedTypeRecord
                            .getValueByPos(MetadataRecordTypes.DERIVEDTYPE_ARECORD_RECORD_FIELD_INDEX);
                    boolean isOpen = ((ABoolean) recordType
                            .getValueByPos(MetadataRecordTypes.RECORDTYPE_ARECORD_ISOPEN_FIELD_INDEX)).getBoolean()
                            .booleanValue();
                    int numberOfFields = ((AOrderedList) recordType
                            .getValueByPos(MetadataRecordTypes.RECORDTYPE_ARECORD_FIELDS_FIELD_INDEX)).size();
                    IACursor cursor = ((AOrderedList) recordType
                            .getValueByPos(MetadataRecordTypes.RECORDTYPE_ARECORD_FIELDS_FIELD_INDEX)).getCursor();
                    String[] fieldNames = new String[numberOfFields];
                    IAType[] fieldTypes = new IAType[numberOfFields];
                    int fieldId = 0;
                    String fieldTypeName;
                    while (cursor.next()) {
                        ARecord field = (ARecord) cursor.get();
                        fieldNames[fieldId] = ((AString) field
                                .getValueByPos(MetadataRecordTypes.FIELD_ARECORD_FIELDNAME_FIELD_INDEX))
                                .getStringValue();
                        fieldTypeName = ((AString) field
                                .getValueByPos(MetadataRecordTypes.FIELD_ARECORD_FIELDTYPE_FIELD_INDEX))
                                .getStringValue();
                        fieldTypes[fieldId] = getTypeFromTypeName(dataverseName, fieldTypeName);
                        fieldId++;
                    }
                    return new Datatype(dataverseName, datatypeName, new ARecordType(datatypeName, fieldNames,
                            fieldTypes, isOpen), isAnonymous);
                }
                case UNION: {
                    IACursor cursor = ((AOrderedList) derivedTypeRecord
                            .getValueByPos(MetadataRecordTypes.DERIVEDTYPE_ARECORD_UNION_FIELD_INDEX)).getCursor();
                    List<IAType> unionList = new ArrayList<IAType>();
                    String itemTypeName;
                    while (cursor.next()) {
                        itemTypeName = ((AString) cursor.get()).getStringValue();
                        unionList.add(getTypeFromTypeName(dataverseName, itemTypeName));
                    }
                    return new Datatype(dataverseName, datatypeName, new AUnionType(unionList, datatypeName),
                            isAnonymous);
                }
                case UNORDEREDLIST: {
                    String unorderedlistTypeName = ((AString) derivedTypeRecord
                            .getValueByPos(MetadataRecordTypes.DERIVEDTYPE_ARECORD_UNORDEREDLIST_FIELD_INDEX))
                            .getStringValue();
                    return new Datatype(dataverseName, datatypeName, new AUnorderedListType(getTypeFromTypeName(
                            dataverseName, unorderedlistTypeName), datatypeName), isAnonymous);
                }
                case ORDEREDLIST: {
                    String orderedlistTypeName = ((AString) derivedTypeRecord
                            .getValueByPos(MetadataRecordTypes.DERIVEDTYPE_ARECORD_ORDEREDLIST_FIELD_INDEX))
                            .getStringValue();
                    return new Datatype(dataverseName, datatypeName, new AOrderedListType(getTypeFromTypeName(
                            dataverseName, orderedlistTypeName), datatypeName), isAnonymous);
                }
                default:
                    throw new UnsupportedOperationException("Unsupported derived type: " + tag);
            }
        }
        return new Datatype(dataverseName, datatypeName, type, false);
    }

    private IAType getTypeFromTypeName(String dataverseName, String typeName) throws MetadataException {
        IAType type = AsterixBuiltinTypeMap.getBuiltinTypes().get(typeName);
        if (type == null) {
            try {
                return metadataNode.getDatatype(txnId, dataverseName, typeName).getDatatype();
            } catch (RemoteException e) {
                throw new MetadataException(e);
            }
        }
        return type;
    }

    @Override
    public ITupleReference getTupleFromMetadataEntity(Datatype dataType) throws IOException {
        // write the key in the first two fields of the tuple
        tupleBuilder.reset();
        aString.setValue(dataType.getDataverseName());
        stringSerde.serialize(aString, tupleBuilder.getDataOutput());
        tupleBuilder.addFieldEndOffset();
        aString.setValue(dataType.getDatatypeName());
        stringSerde.serialize(aString, tupleBuilder.getDataOutput());
        tupleBuilder.addFieldEndOffset();

        // write the payload in the third field of the tuple
        recordBuilder.reset(MetadataRecordTypes.DATATYPE_RECORDTYPE);

        // write field 0
        fieldValue.reset();
        aString.setValue(dataType.getDataverseName());
        stringSerde.serialize(aString, fieldValue.getDataOutput());
        recordBuilder.addField(MetadataRecordTypes.DATATYPE_ARECORD_DATAVERSENAME_FIELD_INDEX, fieldValue);

        // write field 1
        fieldValue.reset();
        aString.setValue(dataType.getDatatypeName());
        stringSerde.serialize(aString, fieldValue.getDataOutput());
        recordBuilder.addField(MetadataRecordTypes.DATATYPE_ARECORD_DATATYPENAME_FIELD_INDEX, fieldValue);

        // write field 2
        ATypeTag tag = dataType.getDatatype().getTypeTag();
        if (isDerivedType(tag)) {
            fieldValue.reset();
            writeDerivedTypeRecord(dataType, fieldValue.getDataOutput());
            recordBuilder.addField(MetadataRecordTypes.DATATYPE_ARECORD_DERIVED_FIELD_INDEX, fieldValue);
        }

        // write field 3
        fieldValue.reset();
        aString.setValue(Calendar.getInstance().getTime().toString());
        stringSerde.serialize(aString, fieldValue.getDataOutput());
        recordBuilder.addField(MetadataRecordTypes.DATATYPE_ARECORD_TIMESTAMP_FIELD_INDEX, fieldValue);

        // write record
        recordBuilder.write(tupleBuilder.getDataOutput(), true);
        tupleBuilder.addFieldEndOffset();

        tuple.reset(tupleBuilder.getFieldEndOffsets(), tupleBuilder.getByteArray());
        return tuple;
    }

    public void writeDerivedTypeRecord(Datatype type, DataOutput out) throws IOException {
        DerivedTypeTag tag;
        IARecordBuilder derivedRecordBuilder = new RecordBuilder();
        ArrayBackedValueStorage fieldValue = new ArrayBackedValueStorage();
        switch (type.getDatatype().getTypeTag()) {
            case UNION:
                tag = DerivedTypeTag.UNION;
                break;
            case ORDEREDLIST:
                tag = DerivedTypeTag.ORDEREDLIST;
                break;
            case UNORDEREDLIST:
                tag = DerivedTypeTag.UNORDEREDLIST;
                break;
            case RECORD:
                tag = DerivedTypeTag.RECORD;
                break;
            default:
                throw new UnsupportedOperationException("No metadata record Type for"
                        + type.getDatatype().getDisplayName());
        }

        derivedRecordBuilder.reset(MetadataRecordTypes.DERIVEDTYPE_RECORDTYPE);

        // write field 0
        fieldValue.reset();
        aString.setValue(tag.toString());
        stringSerde.serialize(aString, fieldValue.getDataOutput());
        derivedRecordBuilder.addField(MetadataRecordTypes.DERIVEDTYPE_ARECORD_TAG_FIELD_INDEX, fieldValue);

        // write field 1
        fieldValue.reset();
        booleanSerde.serialize(type.getIsAnonymous() ? ABoolean.TRUE : ABoolean.FALSE, fieldValue.getDataOutput());
        derivedRecordBuilder.addField(MetadataRecordTypes.DERIVEDTYPE_ARECORD_ISANONYMOUS_FIELD_INDEX, fieldValue);

        switch (tag) {
            case ENUM:
                break;
            case RECORD:
                fieldValue.reset();
                writeRecordType(type, fieldValue.getDataOutput());
                derivedRecordBuilder.addField(MetadataRecordTypes.DERIVEDTYPE_ARECORD_RECORD_FIELD_INDEX, fieldValue);
                break;
            case UNION:
                fieldValue.reset();
                writeUnionType(type, fieldValue.getDataOutput());
                derivedRecordBuilder.addField(MetadataRecordTypes.DERIVEDTYPE_ARECORD_UNION_FIELD_INDEX, fieldValue);
                break;
            case UNORDEREDLIST:
                fieldValue.reset();
                writeCollectionType(type, fieldValue.getDataOutput());
                derivedRecordBuilder.addField(MetadataRecordTypes.DERIVEDTYPE_ARECORD_UNORDEREDLIST_FIELD_INDEX,
                        fieldValue);
                break;
            case ORDEREDLIST:
                fieldValue.reset();
                writeCollectionType(type, fieldValue.getDataOutput());
                derivedRecordBuilder.addField(MetadataRecordTypes.DERIVEDTYPE_ARECORD_ORDEREDLIST_FIELD_INDEX,
                        fieldValue);
                break;
        }
        derivedRecordBuilder.write(out, true);
    }

    private void writeCollectionType(Datatype instance, DataOutput out) throws HyracksDataException {
        AbstractCollectionType listType = (AbstractCollectionType) instance.getDatatype();
        String itemTypeName = listType.getItemType().getTypeName();
        if (isDerivedType(listType.getItemType().getTypeTag())) {
            try {
                itemTypeName = handleNestedDerivedType(itemTypeName, instance.getDatatypeName() + "_ItemType",
                        listType.getItemType(), instance);
            } catch (Exception e) {
                // TODO: This should not be a HyracksDataException. Can't
                // fix this currently because of BTree exception model whose
                // fixes must get in.
                throw new HyracksDataException(e);
            }
        }
        aString.setValue(itemTypeName);
        stringSerde.serialize(aString, out);
    }

    private void writeUnionType(Datatype instance, DataOutput dataOutput) throws HyracksDataException {
        List<IAType> unionList = ((AUnionType) instance.getDatatype()).getUnionList();
        OrderedListBuilder listBuilder = new OrderedListBuilder();
        listBuilder.reset(new AOrderedListType(BuiltinType.ASTRING, null));
        ArrayBackedValueStorage itemValue = new ArrayBackedValueStorage();
        String typeName = null;

        int i = 0;
        for (IAType t : unionList) {
            typeName = t.getTypeName();
            if (isDerivedType(t.getTypeTag())) {
                try {
                    typeName = handleNestedDerivedType(typeName,
                            "Type_#" + i + "_UnionType_" + instance.getDatatypeName(), t, instance);
                } catch (Exception e) {
                    // TODO: This should not be a HyracksDataException. Can't
                    // fix this currently because of BTree exception model whose
                    // fixes must get in.
                    throw new HyracksDataException(e);
                }
            }
            itemValue.reset();
            aString.setValue(typeName);
            stringSerde.serialize(aString, itemValue.getDataOutput());
            listBuilder.addItem(itemValue);
            i++;
        }
        listBuilder.write(dataOutput, true);
    }

    public void writeRecordType(Datatype instance, DataOutput out) throws IOException {

        ArrayBackedValueStorage fieldValue = new ArrayBackedValueStorage();
        ArrayBackedValueStorage itemValue = new ArrayBackedValueStorage();
        IARecordBuilder recordRecordBuilder = new RecordBuilder();
        IARecordBuilder fieldRecordBuilder = new RecordBuilder();

        ARecordType recType = (ARecordType) instance.getDatatype();
        OrderedListBuilder listBuilder = new OrderedListBuilder();
        listBuilder.reset(new AOrderedListType(MetadataRecordTypes.FIELD_RECORDTYPE, null));
        String fieldTypeName = null;
        for (int i = 0; i < recType.getFieldNames().length; i++) {
            fieldTypeName = recType.getFieldTypes()[i].getTypeName();
            if (isDerivedType(recType.getFieldTypes()[i].getTypeTag())) {
                try {
                    fieldTypeName = handleNestedDerivedType(fieldTypeName, "Field_" + recType.getFieldNames()[i]
                            + "_in_" + instance.getDatatypeName(), recType.getFieldTypes()[i], instance);
                } catch (Exception e) {
                    // TODO: This should not be a HyracksDataException. Can't
                    // fix this currently because of BTree exception model whose
                    // fixes must get in.
                    throw new HyracksDataException(e);
                }
            }

            itemValue.reset();
            fieldRecordBuilder.reset(MetadataRecordTypes.FIELD_RECORDTYPE);

            // write field 0
            fieldValue.reset();
            aString.setValue(recType.getFieldNames()[i]);
            stringSerde.serialize(aString, fieldValue.getDataOutput());
            fieldRecordBuilder.addField(MetadataRecordTypes.FIELD_ARECORD_FIELDNAME_FIELD_INDEX, fieldValue);

            // write field 1
            fieldValue.reset();
            aString.setValue(fieldTypeName);
            stringSerde.serialize(aString, fieldValue.getDataOutput());
            fieldRecordBuilder.addField(MetadataRecordTypes.FIELD_ARECORD_FIELDTYPE_FIELD_INDEX, fieldValue);

            // write record
            fieldRecordBuilder.write(itemValue.getDataOutput(), true);

            // add item to the list of fields
            listBuilder.addItem(itemValue);
        }

        recordRecordBuilder.reset(MetadataRecordTypes.RECORD_RECORDTYPE);
        // write field 0
        fieldValue.reset();
        booleanSerde.serialize(recType.isOpen() ? ABoolean.TRUE : ABoolean.FALSE, fieldValue.getDataOutput());
        recordRecordBuilder.addField(MetadataRecordTypes.RECORDTYPE_ARECORD_ISOPEN_FIELD_INDEX, fieldValue);

        // write field 1
        fieldValue.reset();
        listBuilder.write(fieldValue.getDataOutput(), true);
        recordRecordBuilder.addField(MetadataRecordTypes.RECORDTYPE_ARECORD_FIELDS_FIELD_INDEX, fieldValue);

        // write record
        recordRecordBuilder.write(out, true);
    }

    private String handleNestedDerivedType(String typeName, String suggestedTypeName, IAType nestedType,
            Datatype topLevelType) throws Exception {
        MetadataNode mn = MetadataNode.INSTANCE;
        try {
            if (typeName == null) {
                typeName = suggestedTypeName;
                metadataNode.addDatatype(txnId, new Datatype(topLevelType.getDataverseName(), typeName, nestedType,
                        true));

            }
            mn.insertIntoDatatypeSecondaryIndex(txnId, topLevelType.getDataverseName(), typeName,
                    topLevelType.getDatatypeName());

        } catch (BTreeDuplicateKeyException e) {
            // The key may have been inserted by a previous DDL statement or by
            // a previous nested type.
        }
        return typeName;

    }

    private boolean isDerivedType(ATypeTag tag) {
        if (tag == ATypeTag.RECORD || tag == ATypeTag.ORDEREDLIST || tag == ATypeTag.UNORDEREDLIST
                || tag == ATypeTag.UNION)
            return true;
        return false;
    }
}
