/*
 *
 * 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.nio.ByteBuffer;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;

public class MapType extends AbstractPrimitiveType<Map>
{
    private final MapEncoding _mapEncoding;
    private final MapEncoding _shortMapEncoding;
    private EncoderImpl _encoder;

    private AMQPType fixedKeyType;

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

    MapType(final EncoderImpl encoder, final DecoderImpl decoder)
    {
        _encoder = encoder;
        _mapEncoding = new AllMapEncoding(encoder, decoder);
        _shortMapEncoding = new ShortMapEncoding(encoder, decoder);
        encoder.register(Map.class, this);
        decoder.register(this);
    }

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

    public void setKeyEncoding(AMQPType<?> keyType)
    {
        this.fixedKeyType = keyType;
    }

    @Override
    public MapEncoding getEncoding(final Map val)
    {
        int calculatedSize = calculateSize(val, _encoder, fixedKeyType);
        MapEncoding encoding = (val.size() > 127 || calculatedSize >= 254)
                                    ? _mapEncoding
                                    : _shortMapEncoding;

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

    private static int calculateSize(final Map map, EncoderImpl encoder, AMQPType<?> fixedKeyType)
    {
        int len = 0;
        Iterator<Map.Entry> iter = map.entrySet().iterator();

        while (iter.hasNext())
        {
            Map.Entry element = iter.next();

            AMQPType keyType = fixedKeyType;
            if (fixedKeyType == null)
            {
                keyType = encoder.getType(element.getKey());
            }

            TypeEncoding elementEncoding = keyType.getEncoding(element.getKey());
            len += elementEncoding.getConstructorSize()+elementEncoding.getValueSize(element.getKey());
            elementEncoding = encoder.getType(element.getValue()).getEncoding(element.getValue());
            len += elementEncoding.getConstructorSize()+elementEncoding.getValueSize(element.getValue());
        }
        return len;
    }

    private AMQPType<?> getKeyEncoding(EncoderImpl encoder, Object key)
    {
        if (fixedKeyType != null)
        {
            return fixedKeyType;
        }
        else
        {
            return encoder.getType(key);
        }
    }

    private static TypeConstructor<?> findNextDecoder(DecoderImpl decoder, ByteBuffer buffer, TypeConstructor<?> previousConstructor)
    {
        if (previousConstructor == null)
        {
            return decoder.readConstructor();
        }
        else
        {
            buffer.mark();

            byte encodingCode = buffer.get();
            if (encodingCode == EncodingCodes.DESCRIBED_TYPE_INDICATOR || !(previousConstructor instanceof PrimitiveTypeEncoding<?>))
            {
                buffer.reset();
                return decoder.readConstructor();
            }
            else
            {
                PrimitiveTypeEncoding<?> primitiveConstructor = (PrimitiveTypeEncoding<?>) previousConstructor;
                if (encodingCode != primitiveConstructor.getEncodingCode())
                {
                    buffer.reset();
                    return decoder.readConstructor();
                }
            }
        }

        return previousConstructor;
    }

    @Override
    public MapEncoding getCanonicalEncoding()
    {
        return _mapEncoding;
    }

    @Override
    public Collection<MapEncoding> getAllEncodings()
    {
        return Arrays.asList(_shortMapEncoding, _mapEncoding);
    }

    private class AllMapEncoding
            extends LargeFloatingSizePrimitiveTypeEncoding<Map>
            implements MapEncoding
    {

        private Map _value;
        private int _length;

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

        @Override
        protected void writeEncodedValue(final Map map)
        {
            getEncoder().writeRaw(2 * map.size());

            Iterator<Map.Entry> iter = map.entrySet().iterator();

            while (iter.hasNext())
            {
                Map.Entry element = iter.next();

                AMQPType keyType = fixedKeyType;
                if (keyType == null)
                {
                    keyType = getEncoder().getType(element.getKey());
                }

                TypeEncoding elementEncoding = keyType.getEncoding(element.getKey());
                elementEncoding.writeConstructor();
                elementEncoding.writeValue(element.getKey());
                elementEncoding = getEncoder().getType(element.getValue()).getEncoding(element.getValue());
                elementEncoding.writeConstructor();
                elementEncoding.writeValue(element.getValue());
            }
        }

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

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

        @Override
        public MapType getType()
        {
            return MapType.this;
        }

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

        @Override
        public Map readValue()
        {
            DecoderImpl decoder = getDecoder();
            ByteBuffer buffer = decoder.getByteBuffer();

            int size = decoder.readRawInt();
            // todo - limit the decoder with size
            int count = decoder.readRawInt();
            if (count > decoder.getByteBufferRemaining()) {
                throw new IllegalArgumentException("Map element count "+count+" is specified to be greater than the amount of data available ("+
                                                   decoder.getByteBufferRemaining()+")");
            }

            TypeConstructor<?> keyConstructor = null;
            TypeConstructor<?> valueConstructor = null;

            Map<Object, Object> map = new LinkedHashMap<>(count);
            for(int i = 0; i < count / 2; i++)
            {
                keyConstructor = findNextDecoder(decoder, buffer, keyConstructor);
                if(keyConstructor == null)
                {
                    throw new DecodeException("Unknown constructor");
                }

                Object key = keyConstructor.readValue();

                boolean arrayType = false;
                byte code = buffer.get(buffer.position());
                switch (code)
                {
                    case EncodingCodes.ARRAY8:
                    case EncodingCodes.ARRAY32:
                        arrayType = true;
                }

                valueConstructor = findNextDecoder(decoder, buffer, valueConstructor);
                if (valueConstructor == null)
                {
                    throw new DecodeException("Unknown constructor");
                }

                final Object value;

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

                map.put(key, value);
            }

            return map;
        }

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

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

    private class ShortMapEncoding
            extends SmallFloatingSizePrimitiveTypeEncoding<Map>
            implements MapEncoding
    {

        private Map _value;
        private int _length;

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

        @Override
        protected void writeEncodedValue(final Map map)
        {
            getEncoder().writeRaw((byte)(2 * map.size()));

            Iterator<Map.Entry> iter = map.entrySet().iterator();
            while (iter.hasNext())
            {
                Map.Entry element = iter.next();

                AMQPType keyType = fixedKeyType;
                if (keyType == null)
                {
                    keyType = getEncoder().getType(element.getKey());
                }

                TypeEncoding elementEncoding = keyType.getEncoding(element.getKey());
                elementEncoding.writeConstructor();
                elementEncoding.writeValue(element.getKey());
                elementEncoding = getEncoder().getType(element.getValue()).getEncoding(element.getValue());
                elementEncoding.writeConstructor();
                elementEncoding.writeValue(element.getValue());
            }
        }

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

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

        @Override
        public MapType getType()
        {
            return MapType.this;
        }

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

        @Override
        public Map readValue()
        {
            DecoderImpl decoder = getDecoder();
            ByteBuffer buffer = decoder.getByteBuffer();

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

            TypeConstructor<?> keyConstructor = null;
            TypeConstructor<?> valueConstructor = null;

            Map<Object, Object> map = new LinkedHashMap<>(count);
            for(int i = 0; i < count / 2; i++)
            {
                keyConstructor = findNextDecoder(decoder, buffer, keyConstructor);
                if(keyConstructor == null)
                {
                    throw new DecodeException("Unknown constructor");
                }

                Object key = keyConstructor.readValue();

                boolean arrayType = false;
                byte code = buffer.get(buffer.position());
                switch (code)
                {
                    case EncodingCodes.ARRAY8:
                    case EncodingCodes.ARRAY32:
                        arrayType = true;
                }

                valueConstructor = findNextDecoder(decoder, buffer, valueConstructor);
                if(valueConstructor== null)
                {
                    throw new DecodeException("Unknown constructor");
                }

                final Object value;

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

                map.put(key, value);
            }

            return map;
        }

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

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