/*
 *
 * 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;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

public class ListType extends AbstractPrimitiveType<List>
{
    private final ListEncoding _listEncoding;
    private final ListEncoding _shortListEncoding;
    private final ListEncoding _zeroListEncoding;
    private EncoderImpl _encoder;

    private static interface ListEncoding extends PrimitiveTypeEncoding<List>
    {
        void setValue(List value, int length);
    }

    ListType(final EncoderImpl encoder, final DecoderImpl decoder)
    {
        _encoder = encoder;
        _listEncoding = new AllListEncoding(encoder, decoder);
        _shortListEncoding = new ShortListEncoding(encoder, decoder);
        _zeroListEncoding = new ZeroListEncoding(encoder, decoder);
        encoder.register(List.class, this);
        decoder.register(this);
    }

    public Class<List> getTypeClass()
    {
        return List.class;
    }

    public ListEncoding getEncoding(final List val)
    {
        int calculatedSize = calculateSize(val, _encoder);
        ListEncoding encoding = val.isEmpty()
                                    ? _zeroListEncoding
                                    : (val.size() > 255 || calculatedSize >= 254)
                                        ? _listEncoding
                                        : _shortListEncoding;

        encoding.setValue(val, calculatedSize);
        return encoding;
    }

    private static int calculateSize(final List val, EncoderImpl encoder)
    {
        int len = 0;
        final int count = val.size();

        for(int i = 0; i < count; i++)
        {
            Object element = val.get(i);
            AMQPType type = encoder.getType(element);
            if(type == null)
            {
                throw new IllegalArgumentException("No encoding defined for type: " + element.getClass());
            }
            TypeEncoding elementEncoding = type.getEncoding(element);
            len += elementEncoding.getConstructorSize()+elementEncoding.getValueSize(element);
        }
        return len;
    }

    public ListEncoding getCanonicalEncoding()
    {
        return _listEncoding;
    }

    public Collection<ListEncoding> getAllEncodings()
    {
        return Arrays.asList(_zeroListEncoding, _shortListEncoding, _listEncoding);
    }

    private class AllListEncoding
            extends LargeFloatingSizePrimitiveTypeEncoding<List>
            implements ListEncoding
    {

        private List _value;
        private int _length;

        public AllListEncoding(final EncoderImpl encoder, final DecoderImpl decoder)
        {
            super(encoder, decoder);
        }

        @Override
        protected void writeEncodedValue(final List val)
        {
            getEncoder().writeRaw(val.size());

            final int count = val.size();

            for(int i = 0; i < count; i++)
            {
                Object element = val.get(i);
                TypeEncoding elementEncoding = getEncoder().getType(element).getEncoding(element);
                elementEncoding.writeConstructor();
                elementEncoding.writeValue(element);
            }
        }

        @Override
        protected int getEncodedValueSize(final List val)
        {
            return 4 + ((val == _value) ? _length : calculateSize(val, getEncoder()));
        }


        @Override
        public byte getEncodingCode()
        {
            return EncodingCodes.LIST32;
        }

        public ListType getType()
        {
            return ListType.this;
        }

        public boolean encodesSuperset(final TypeEncoding<List> encoding)
        {
            return (getType() == encoding.getType());
        }

        public List readValue()
        {
            DecoderImpl decoder = getDecoder();
            ReadableBuffer buffer = decoder.getBuffer();

            int size = decoder.readRawInt();
            // todo - limit the decoder with size
            int count = decoder.readRawInt();
            // Ensure we do not allocate an array of size greater then the available data, otherwise there is a risk for an OOM error
            if (count > decoder.getByteBufferRemaining()) {
                throw new IllegalArgumentException("List element count "+count+" is specified to be greater than the amount of data available ("+
                                                   decoder.getByteBufferRemaining()+")");
            }

            TypeConstructor<?> typeConstructor = null;

            List<Object> list = new ArrayList<>(count);
            for (int i = 0; i < count; i++)
            {
                boolean arrayType = false;
                byte encodingCode = buffer.get(buffer.position());
                switch (encodingCode)
                {
                    case EncodingCodes.ARRAY8:
                    case EncodingCodes.ARRAY32:
                        arrayType = true;
                }

                // Whenever we can just reuse the previously used TypeDecoder instead
                // of spending time looking up the same one again.
                if (typeConstructor == null)
                {
                    typeConstructor = getDecoder().readConstructor();
                }
                else
                {
                    if (encodingCode == EncodingCodes.DESCRIBED_TYPE_INDICATOR || !(typeConstructor instanceof PrimitiveTypeEncoding<?>))
                    {
                        typeConstructor = getDecoder().readConstructor();
                    }
                    else
                    {
                        PrimitiveTypeEncoding<?> primitiveConstructor = (PrimitiveTypeEncoding<?>) typeConstructor;
                        if (encodingCode != primitiveConstructor.getEncodingCode())
                        {
                            typeConstructor = getDecoder().readConstructor();
                        }
                        else
                        {
                            // consume the encoding code byte for real
                            encodingCode = buffer.get();
                        }
                    }
                }

                if(typeConstructor == null)
                {
                    throw new DecodeException("Unknown constructor");
                }

                final Object value;

                if (arrayType)
                {
                    value = ((ArrayType.ArrayEncoding) typeConstructor).readValueArray();
                }
                else
                {
                    value = typeConstructor.readValue();
                }

                list.add(value);
            }

            return list;
        }

        public void skipValue()
        {
            DecoderImpl decoder = getDecoder();
            ReadableBuffer buffer = decoder.getBuffer();
            int size = decoder.readRawInt();
            buffer.position(buffer.position() + size);
        }

        public void setValue(final List value, final int length)
        {
            _value = value;
            _length = length;
        }
    }

    private class ShortListEncoding
            extends SmallFloatingSizePrimitiveTypeEncoding<List>
            implements ListEncoding
    {

        private List _value;
        private int _length;

        public ShortListEncoding(final EncoderImpl encoder, final DecoderImpl decoder)
        {
            super(encoder, decoder);
        }

        @Override
        protected void writeEncodedValue(final List val)
        {
            getEncoder().writeRaw((byte)val.size());

            final int count = val.size();

            for(int i = 0; i < count; i++)
            {
                Object element = val.get(i);
                TypeEncoding elementEncoding = getEncoder().getType(element).getEncoding(element);
                elementEncoding.writeConstructor();
                elementEncoding.writeValue(element);
            }
        }

        @Override
        protected int getEncodedValueSize(final List val)
        {
            return 1 + ((val == _value) ? _length : calculateSize(val, getEncoder()));
        }


        @Override
        public byte getEncodingCode()
        {
            return EncodingCodes.LIST8;
        }

        public ListType getType()
        {
            return ListType.this;
        }

        public boolean encodesSuperset(final TypeEncoding<List> encoder)
        {
            return encoder == this;
        }

        public List readValue()
        {
            DecoderImpl decoder = getDecoder();
            ReadableBuffer buffer = decoder.getBuffer();

            int size = ((int)decoder.readRawByte()) & 0xff;
            // todo - limit the decoder with size
            int count = ((int)decoder.readRawByte()) & 0xff;

            TypeConstructor<?> typeConstructor = null;

            List<Object> list = new ArrayList<>(count);
            for (int i = 0; i < count; i++)
            {
                boolean arrayType = false;
                byte encodingCode = buffer.get(buffer.position());
                switch (encodingCode)
                {
                    case EncodingCodes.ARRAY8:
                    case EncodingCodes.ARRAY32:
                        arrayType = true;
                }

                // Whenever we can just reuse the previously used TypeDecoder instead
                // of spending time looking up the same one again.
                if (typeConstructor == null)
                {
                    typeConstructor = getDecoder().readConstructor();
                }
                else
                {
                    if (encodingCode == EncodingCodes.DESCRIBED_TYPE_INDICATOR || !(typeConstructor instanceof PrimitiveTypeEncoding<?>))
                    {
                        typeConstructor = getDecoder().readConstructor();
                    }
                    else
                    {
                        PrimitiveTypeEncoding<?> primitiveConstructor = (PrimitiveTypeEncoding<?>) typeConstructor;
                        if (encodingCode != primitiveConstructor.getEncodingCode())
                        {
                            typeConstructor = getDecoder().readConstructor();
                        }
                        else
                        {
                            // consume the encoding code byte for real
                            encodingCode = buffer.get();
                        }
                    }
                }

                if (typeConstructor == null)
                {
                    throw new DecodeException("Unknown constructor");
                }

                final Object value;

                if (arrayType)
                {
                    value = ((ArrayType.ArrayEncoding) typeConstructor).readValueArray();
                }
                else
                {
                    value = typeConstructor.readValue();
                }

                list.add(value);
            }

            return list;
        }

        public void skipValue()
        {
            DecoderImpl decoder = getDecoder();
            ReadableBuffer buffer = decoder.getBuffer();
            int size = ((int)decoder.readRawByte()) & 0xff;
            buffer.position(buffer.position() + size);
        }

        public void setValue(final List value, final int length)
        {
            _value = value;
            _length = length;
        }
    }


    private class ZeroListEncoding
            extends FixedSizePrimitiveTypeEncoding<List>
            implements ListEncoding
    {
        public ZeroListEncoding(final EncoderImpl encoder, final DecoderImpl decoder)
        {
            super(encoder, decoder);
        }

        @Override
        public byte getEncodingCode()
        {
            return EncodingCodes.LIST0;
        }

        @Override
        protected int getFixedSize()
        {
            return 0;
        }

        public ListType getType()
        {
           return ListType.this;
        }

        public void setValue(List value, int length)
        {
        }

        public void writeValue(final List val)
        {
        }

        public boolean encodesSuperset(final TypeEncoding<List> encoder)
        {
            return encoder == this;
        }

        public List readValue()
        {
            return Collections.EMPTY_LIST;
        }
    }
}
