/*
 *
 * 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.server.protocol.v0_8;

import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.qpid.server.bytebuffer.QpidByteBuffer;

public class FieldTable
{
    private static final Logger LOGGER = LoggerFactory.getLogger(FieldTable.class);
    private static final String STRICT_AMQP_NAME = "STRICT_AMQP";
    private static final boolean STRICT_AMQP = Boolean.valueOf(System.getProperty(STRICT_AMQP_NAME, "false"));
    private static final AMQTypedValue NOT_PRESENT = AMQType.VOID.asTypedValue(null);

    public static final FieldTable EMPTY = FieldTable.convertToFieldTable(Collections.emptyMap());

    private QpidByteBuffer _encodedForm;
    private boolean _decoded;
    private final Map<String, AMQTypedValue> _properties;
    private final long _encodedSize;
    private final boolean _strictAMQP;

    FieldTable(QpidByteBuffer input, int len)
    {
        _strictAMQP = STRICT_AMQP;
        _encodedForm = input.view(0,len);
        input.position(input.position()+len);
        _encodedSize = len;
        _properties = new LinkedHashMap<>();
    }

    FieldTable(QpidByteBuffer buffer)
    {
        _strictAMQP = STRICT_AMQP;
        _encodedForm = buffer.duplicate();
        _encodedSize = buffer.remaining();
        _properties = new LinkedHashMap<>();
    }

    FieldTable(Map<String, Object> properties)
    {
        this(properties, STRICT_AMQP);
    }

    FieldTable(Map<String, Object> properties, boolean strictAMQP)
    {
        _strictAMQP = strictAMQP;
        long size = 0;
        Map<String, AMQTypedValue> m = new LinkedHashMap<>();
        if (properties != null && !properties.isEmpty())
        {
            m = new LinkedHashMap<>();
            for (Map.Entry<String, Object> e : properties.entrySet())
            {
                String key = e.getKey();
                Object val = e.getValue();
                checkPropertyName(key);
                AMQTypedValue value = getAMQTypeValue(val);
                size += EncodingUtils.encodedShortStringLength(e.getKey()) + 1 + value.getEncodingSize();
                m.put(e.getKey(), value);
            }
        }
        _properties = m;
        _encodedSize = size;
        _decoded = true;
    }

    private synchronized AMQTypedValue getProperty(String key)
    {
        AMQTypedValue value = _properties.get(key);
        if (value == null && !_decoded)
        {
            value = findValueForKey(key);
            _properties.put(key, value);
        }
        return value;
    }

    private void decode()
    {
        if (_encodedSize > 0 && _encodedForm != null)
        {
            if (!_properties.isEmpty())
            {
                _properties.clear();
            }
            _encodedForm.mark();
            try
            {
                do
                {
                    final String key = AMQShortString.readAMQShortStringAsString(_encodedForm);

                    checkPropertyName(key);
                    AMQTypedValue value = AMQTypedValue.readFromBuffer(_encodedForm);
                    _properties.put(key, value);
                }
                while (_encodedForm.hasRemaining());
            }
            finally
            {
                _encodedForm.reset();
            }

            final long recalculateEncodedSize = recalculateEncodedSize();
            if (_encodedSize != recalculateEncodedSize)
            {
                throw new IllegalStateException(String.format(
                        "Malformed field table detected: provided encoded size '%d' does not equal calculated size '%d'",
                        _encodedSize,
                        recalculateEncodedSize));
            }
        }
    }

    private void decodeIfNecessary()
    {
        if (!_decoded)
        {
            try
            {
                decode();
            }
            finally
            {
                _decoded = true;
            }
        }
    }

    private AMQTypedValue getAMQTypeValue(final Object object) throws AMQPInvalidClassException
    {
        if (object == null)
        {
            return AMQType.VOID.asTypedValue(null);
        }
        else if (object instanceof Boolean)
        {
            return AMQType.BOOLEAN.asTypedValue(object);
        }
        else if (object instanceof Byte)
        {
            return AMQType.BYTE.asTypedValue(object);
        }
        else if (object instanceof Short)
        {
            return AMQType.SHORT.asTypedValue(object);
        }
        else if (object instanceof Integer)
        {
            return AMQTypedValue.createAMQTypedValue((int) object);
        }
        else if (object instanceof Long)
        {
            return AMQTypedValue.createAMQTypedValue((long) object);
        }
        else if (object instanceof Float)
        {
            return AMQType.FLOAT.asTypedValue(object);
        }
        else if (object instanceof Double)
        {
            return AMQType.DOUBLE.asTypedValue(object);
        }
        else if (object instanceof String)
        {
            return AMQType.LONG_STRING.asTypedValue(object);
        }
        else if (object instanceof Character)
        {
            return AMQType.ASCII_CHARACTER.asTypedValue(object);
        }
        else if (object instanceof FieldTable)
        {
            return AMQType.FIELD_TABLE.asTypedValue(object);
        }
        else if (object instanceof Map)
        {
            @SuppressWarnings("unchecked")
            Map<String, Object> map = (Map<String, Object>) object;
            return AMQType.FIELD_TABLE.asTypedValue(FieldTable.convertToFieldTable(map));
        }
        else if (object instanceof Collection)
        {
            return AMQType.FIELD_ARRAY.asTypedValue(object);
        }
        else if (object instanceof Date)
        {
            return AMQType.TIMESTAMP.asTypedValue(((Date) object).getTime());
        }
        else if (object instanceof BigDecimal)
        {
            final BigDecimal decimal = (BigDecimal) object;
            if (decimal.longValue() > Integer.MAX_VALUE)
            {
                throw new UnsupportedOperationException(String.format("AMQP does not support decimals larger than %d",
                                                                      Integer.MAX_VALUE));
            }

            if (decimal.scale() > Byte.MAX_VALUE)
            {
                throw new UnsupportedOperationException(String.format(
                        "AMQP does not support decimal scales larger than %d",
                        Byte.MAX_VALUE));
            }

            return AMQType.DECIMAL.asTypedValue(decimal);
        }
        else if (object instanceof byte[])
        {
            return AMQType.BINARY.asTypedValue(object);
        }
        else if (object instanceof UUID)
        {
            return AMQType.LONG_STRING.asTypedValue(object.toString());
        }

        throw new AMQPInvalidClassException(AMQPInvalidClassException.INVALID_OBJECT_MSG + object.getClass());
    }

    // ***** Methods

    @Override
    public String toString()
    {
        return getProperties().toString();
    }

    private void checkPropertyName(String propertyName)
    {
        if (propertyName == null)
        {
            throw new IllegalArgumentException("Property name must not be null");
        }
        else if (propertyName.length() == 0)
        {
            throw new IllegalArgumentException("Property name must not be the empty string");
        }

        if (_strictAMQP)
        {
            checkIdentiferFormat(propertyName);
        }
    }

    private static void checkIdentiferFormat(String propertyName)
    {
        // AMQP Spec: 4.2.5.5 Field Tables
        // Guidelines for implementers:
        // * Field names MUST start with a letter, '$' or '#' and may continue with
        // letters, '$' or '#', digits, or underlines, to a maximum length of 128
        // characters.
        // * The server SHOULD validate field names and upon receiving an invalid
        // field name, it SHOULD signal a connection exception with reply code
        // 503 (syntax error). Conformance test: amq_wlp_table_01.
        // * A peer MUST handle duplicate fields by using only the first instance.

        // AMQP length limit
        if (propertyName.length() > 128)
        {
            throw new IllegalArgumentException("AMQP limits property names to 128 characters");
        }

        // AMQ start character
        if (!(Character.isLetter(propertyName.charAt(0)) || (propertyName.charAt(0) == '$')
              || (propertyName.charAt(0) == '#') || (propertyName.charAt(0)
                                                     == '_'))) // Not official AMQP added for JMS.
        {
            throw new IllegalArgumentException("Identifier '" + propertyName
                                               + "' does not start with a valid AMQP start character");
        }
    }

    // *************************  Byte Buffer Processing

    public synchronized void writeToBuffer(QpidByteBuffer buffer)
    {
        if (LOGGER.isDebugEnabled())
        {
            LOGGER.debug("FieldTable::writeToBuffer: Writing encoded length of " + getEncodedSize() + "...");
            if (_decoded)
            {
                LOGGER.debug(getProperties().toString());
            }
        }

        buffer.putUnsignedInt(getEncodedSize());

        putDataInBuffer(buffer);
    }

    public synchronized byte[] getDataAsBytes()
    {
        if (_encodedForm == null)
        {
            byte[] data = new byte[(int) getEncodedSize()];
            QpidByteBuffer buf = QpidByteBuffer.wrap(data);
            putDataInBuffer(buf);
            return data;
        }
        else
        {
            byte[] encodedCopy = new byte[_encodedForm.remaining()];
            _encodedForm.copyTo(encodedCopy);
            return encodedCopy;
        }
    }

    public long getEncodedSize()
    {
        return _encodedSize;
    }

    private synchronized long recalculateEncodedSize()
    {
        long size = 0L;
        for (Map.Entry<String, AMQTypedValue> e : _properties.entrySet())
        {
            String key = e.getKey();
            AMQTypedValue value = e.getValue();
            size += EncodingUtils.encodedShortStringLength(key) + 1 + value.getEncodingSize();
        }
        return size;
    }

    public static Map<String, Object> convertToMap(final FieldTable fieldTable)
    {
        final Map<String, Object> map = new HashMap<>();

        if (fieldTable != null)
        {
            Map<String, AMQTypedValue> properties = fieldTable.getProperties();
            if (properties != null)
            {
                for (Map.Entry<String, AMQTypedValue> e : properties.entrySet())
                {
                    Object val = e.getValue().getValue();
                    if (val instanceof AMQShortString)
                    {
                        val = val.toString();
                    }
                    else if (val instanceof FieldTable)
                    {
                        val = FieldTable.convertToMap((FieldTable) val);
                    }
                    map.put(e.getKey(), val);
                }
            }
        }
        return map;
    }

    public synchronized void clearEncodedForm()
    {
        try
        {
            decodeIfNecessary();
        }
        finally
        {
            if (_encodedForm != null)
            {
                _encodedForm.dispose();
                _encodedForm = null;
            }
        }
    }

    public synchronized void dispose()
    {
        if (_encodedForm != null)
        {
            _encodedForm.dispose();
            _encodedForm = null;
        }
        _properties.clear();
    }

    public int size()
    {
        return getProperties().size();
    }

    public boolean isEmpty()
    {
        return size() == 0;
    }

    public boolean containsKey(String key)
    {
        return getProperties().containsKey(key);
    }

    public Set<String> keys()
    {
        return new LinkedHashSet<>(getProperties().keySet());
    }

    public Object get(String key)
    {
        checkPropertyName(key);
        AMQTypedValue value = getProperty(key);
        if (value != null && value != NOT_PRESENT)
        {
            return value.getValue();
        }
        else
        {
            return null;
        }
    }

    private void putDataInBuffer(QpidByteBuffer buffer)
    {
        if (_encodedForm != null)
        {
            byte[] encodedCopy = new byte[_encodedForm.remaining()];
            _encodedForm.copyTo(encodedCopy);

            buffer.put(encodedCopy);
        }
        else if (!_properties.isEmpty())
        {
            for (final Map.Entry<String, AMQTypedValue> me : _properties.entrySet())
            {
                EncodingUtils.writeShortStringBytes(buffer, me.getKey());
                me.getValue().writeToBuffer(buffer);
            }
        }
    }


    @Override
    public int hashCode()
    {
        return getProperties().hashCode();
    }

    @Override
    public boolean equals(Object o)
    {
        if (o == this)
        {
            return true;
        }

        if (o == null || getClass() != o.getClass())
        {
            return false;
        }

        FieldTable f = (FieldTable) o;
        return getProperties().equals(f.getProperties());
    }

    private synchronized Map<String, AMQTypedValue> getProperties()
    {
        decodeIfNecessary();
        return _properties;
    }

    private AMQTypedValue findValueForKey(String key)
    {
        byte[] keyBytes = key.getBytes(StandardCharsets.UTF_8);
        _encodedForm.mark();
        try
        {
            while (_encodedForm.hasRemaining())
            {
                final byte[] bytes = AMQShortString.readAMQShortStringAsBytes(_encodedForm);
                if (Arrays.equals(keyBytes, bytes))
                {
                    return AMQTypedValue.readFromBuffer(_encodedForm);
                }
                else
                {
                    AMQType type = AMQTypeMap.getType(_encodedForm.get());
                    type.skip(_encodedForm);
                }
            }
        }
        finally
        {
            _encodedForm.reset();
        }
        return NOT_PRESENT;
    }

    public static FieldTable convertToFieldTable(Map<String, Object> map)
    {
        if (map != null)
        {
            return new FieldTable(map);
        }
        else
        {
            return null;
        }
    }

    public synchronized void validate()
    {
        decodeIfNecessary();
    }
}
