/*
 * 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.qpid.proton.codec.transport;

import java.util.Collection;

import org.apache.qpid.proton.amqp.Symbol;
import org.apache.qpid.proton.amqp.UnsignedByte;
import org.apache.qpid.proton.amqp.UnsignedLong;
import org.apache.qpid.proton.amqp.transport.DeliveryState;
import org.apache.qpid.proton.amqp.transport.ReceiverSettleMode;
import org.apache.qpid.proton.amqp.transport.Transfer;
import org.apache.qpid.proton.codec.AMQPType;
import org.apache.qpid.proton.codec.FastPathDescribedTypeConstructor;
import org.apache.qpid.proton.codec.DecodeException;
import org.apache.qpid.proton.codec.Decoder;
import org.apache.qpid.proton.codec.DecoderImpl;
import org.apache.qpid.proton.codec.EncoderImpl;
import org.apache.qpid.proton.codec.EncodingCodes;
import org.apache.qpid.proton.codec.TypeEncoding;
import org.apache.qpid.proton.codec.WritableBuffer;

/**
 * Fast TrasnferType encoder
 */
public class FastPathTransferType implements AMQPType<Transfer>, FastPathDescribedTypeConstructor<Transfer> {

    private static final Object[] DESCRIPTORS =
    {
        UnsignedLong.valueOf(0x0000000000000014L), Symbol.valueOf("amqp:transfer:list"),
    };

    private final TransferType transferType;

    public FastPathTransferType(EncoderImpl encoder) {
        this.transferType = new TransferType(encoder);
    }

    public EncoderImpl getEncoder() {
        return transferType.getEncoder();
    }

    public DecoderImpl getDecoder() {
        return transferType.getDecoder();
    }

    @Override
    public Transfer readValue() {
        DecoderImpl decoder = getDecoder();
        byte typeCode = decoder.getByteBuffer().get();

        @SuppressWarnings("unused")
        int size = 0;
        int count = 0;

        switch (typeCode) {
            case EncodingCodes.LIST0:
                // TODO - Technically invalid however old decoder also allowed this.
                break;
            case EncodingCodes.LIST8:
                size = ((int)decoder.getByteBuffer().get()) & 0xff;
                count = ((int)decoder.getByteBuffer().get()) & 0xff;
                break;
            case EncodingCodes.LIST32:
                size = decoder.getByteBuffer().getInt();
                count = decoder.getByteBuffer().getInt();
                break;
            default:
                throw new DecodeException("Incorrect type found in Transfer encoding: " + typeCode);
        }

        Transfer transfer = new Transfer();

        for (int index = 0; index < count; ++index) {
            switch (index) {
                case 0:
                    transfer.setHandle(decoder.readUnsignedInteger());
                    break;
                case 1:
                    transfer.setDeliveryId(decoder.readUnsignedInteger());
                    break;
                case 2:
                    transfer.setDeliveryTag(decoder.readBinary());
                    break;
                case 3:
                    transfer.setMessageFormat(decoder.readUnsignedInteger());
                    break;
                case 4:
                    transfer.setSettled(decoder.readBoolean());
                    break;
                case 5:
                    transfer.setMore(decoder.readBoolean(false));
                    break;
                case 6:
                    UnsignedByte rcvSettleMode = decoder.readUnsignedByte();
                    transfer.setRcvSettleMode(rcvSettleMode == null ? null : ReceiverSettleMode.values()[rcvSettleMode.intValue()]);
                    break;
                case 7:
                    transfer.setState((DeliveryState) decoder.readObject());
                    break;
                case 8:
                    transfer.setResume(decoder.readBoolean(false));
                    break;
                case 9:
                    transfer.setAborted(decoder.readBoolean(false));
                    break;
                case 10:
                    transfer.setBatchable(decoder.readBoolean(false));
                    break;
                default:
                    throw new IllegalStateException("To many entries in Transfer encoding");
            }
        }

        return transfer;
    }

    @Override
    public void skipValue() {
        getDecoder().readConstructor().skipValue();
    }

    @Override
    public boolean encodesJavaPrimitive() {
        return false;
    }

    @Override
    public Class<Transfer> getTypeClass() {
        return Transfer.class;
    }

    @Override
    public TypeEncoding<Transfer> getEncoding(Transfer transfer) {
        return transferType.getEncoding(transfer);
    }

    @Override
    public TypeEncoding<Transfer> getCanonicalEncoding() {
        return transferType.getCanonicalEncoding();
    }

    @Override
    public Collection<? extends TypeEncoding<Transfer>> getAllEncodings() {
        return transferType.getAllEncodings();
    }

    @Override
    public void write(Transfer value) {
        WritableBuffer buffer = getEncoder().getBuffer();
        int count = getElementCount(value);
        byte encodingCode = deduceEncodingCode(value, count);

        buffer.put(EncodingCodes.DESCRIBED_TYPE_INDICATOR);
        getEncoder().writeUnsignedLong(transferType.getDescriptor());

        final int fieldWidth;

        if (encodingCode == EncodingCodes.LIST8) {
            fieldWidth = 1;
            buffer.put(EncodingCodes.LIST8);
        } else {
            fieldWidth = 4;
            buffer.put(EncodingCodes.LIST32);
        }

        int startIndex = buffer.position();

        // Reserve space for the size and write the count of list elements.
        if (fieldWidth == 1) {
            buffer.put((byte) 0);
            buffer.put((byte) count);
        } else {
            buffer.putInt(0);
            buffer.putInt(count);
        }

        // Write the list elements and then compute total size written.
        for (int i = 0; i < count; ++i) {
            writeElement(value, i);
        }

        // Move back and write the size
        int endIndex = buffer.position();
        int writeSize = endIndex - startIndex - fieldWidth;

        buffer.position(startIndex);
        if (fieldWidth == 1) {
            buffer.put((byte) writeSize);
        } else {
            buffer.putInt(writeSize);
        }
        buffer.position(endIndex);
    }

    private void writeElement(Transfer transfer, int index) {
        switch (index) {
            case 0:
                getEncoder().writeUnsignedInteger(transfer.getHandle());
                break;
            case 1:
                getEncoder().writeUnsignedInteger(transfer.getDeliveryId());
                break;
            case 2:
                getEncoder().writeBinary(transfer.getDeliveryTag());
                break;
            case 3:
                getEncoder().writeUnsignedInteger(transfer.getMessageFormat());
                break;
            case 4:
                getEncoder().writeBoolean(transfer.getSettled());
                break;
            case 5:
                getEncoder().writeBoolean(transfer.getMore());
                break;
            case 6:
                ReceiverSettleMode rcvSettleMode = transfer.getRcvSettleMode();
                getEncoder().writeObject(rcvSettleMode == null ? null : rcvSettleMode.getValue());
                break;
            case 7:
                getEncoder().writeObject(transfer.getState());
                break;
            case 8:
                getEncoder().writeBoolean(transfer.getResume());
                break;
            case 9:
                getEncoder().writeBoolean(transfer.getAborted());
                break;
            case 10:
                getEncoder().writeBoolean(transfer.getBatchable());
                break;
            default:
                throw new IllegalArgumentException("Unknown Transfer value index: " + index);
        }
    }

    private byte deduceEncodingCode(Transfer value, int elementCount) {
        if (value.getState() != null) {
            return EncodingCodes.LIST32;
        } else if (value.getDeliveryTag() != null && value.getDeliveryTag().getLength() > 200) {
            return EncodingCodes.LIST32;
        } else {
            return EncodingCodes.LIST8;
        }
    }

    private int getElementCount(Transfer transfer) {
        if (transfer.getBatchable()) {
            return 11;
        } else if (transfer.getAborted()) {
            return 10;
        } else if (transfer.getResume()) {
            return 9;
        } else if (transfer.getState() != null) {
            return 8;
        } else if (transfer.getRcvSettleMode() != null) {
            return 7;
        } else if (transfer.getMore()) {
            return 6;
        } else if (transfer.getSettled() != null) {
            return 5;
        } else if (transfer.getMessageFormat() != null) {
            return 4;
        } else if (transfer.getDeliveryTag() != null) {
            return 3;
        } else if (transfer.getDeliveryId() != null) {
            return 2;
        } else {
            return 1;
        }
    }

    public static void register(Decoder decoder, EncoderImpl encoder) {
        FastPathTransferType type = new FastPathTransferType(encoder);
        for(Object descriptor : DESCRIPTORS)
        {
            decoder.register(descriptor, (FastPathDescribedTypeConstructor<?>) type);
        }
        encoder.register(type);
    }
}
