/*
 *
 * 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.client.message;

import java.net.URISyntaxException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageNotWriteableException;
import javax.jms.Queue;

import org.apache.qpid.QpidException;
import org.apache.qpid.client.AMQAnyDestination;
import org.apache.qpid.client.AMQDestination;
import org.apache.qpid.client.AMQQueue;
import org.apache.qpid.client.AMQSession;
import org.apache.qpid.client.AMQSession_0_8;
import org.apache.qpid.client.AMQTopic;
import org.apache.qpid.client.CustomJMSXProperty;
import org.apache.qpid.exchange.ExchangeDefaults;
import org.apache.qpid.framing.AMQShortString;
import org.apache.qpid.framing.BasicContentHeaderProperties;
import org.apache.qpid.messaging.Address;
import org.apache.qpid.url.AMQBindingURL;
import org.apache.qpid.url.BindingURL;


public class AMQMessageDelegate_0_8 extends AbstractAMQMessageDelegate
{
    private static final float DESTINATION_CACHE_LOAD_FACTOR = 0.75f;
    private static final int DESTINATION_CACHE_SIZE = 500;
    private static final int DESTINATION_CACHE_CAPACITY = (int) (DESTINATION_CACHE_SIZE / DESTINATION_CACHE_LOAD_FACTOR);

    private static final Map<String, Destination> _destinationCache =
            Collections.synchronizedMap(new LinkedHashMap<String,Destination>(DESTINATION_CACHE_CAPACITY,
                                                                              DESTINATION_CACHE_LOAD_FACTOR,
                                                                              true)
    {
        @Override
        protected boolean removeEldestEntry(Map.Entry<String, Destination> eldest)
        {
            return size() >= DESTINATION_CACHE_SIZE;
        }
    });

    public static final String JMS_TYPE = "x-jms-type";
    public static final boolean STRICT_JMS = Boolean.getBoolean("strict-jms");


    private boolean _readableProperties = false;

    private Destination _destination;
    private JMSHeaderAdapter _headerAdapter;
    private static final boolean STRICT_AMQP_COMPLIANCE =
            Boolean.parseBoolean(System.getProperties().getProperty(AMQSession.STRICT_AMQP, AMQSession.STRICT_AMQP_DEFAULT));

    private BasicContentHeaderProperties _contentHeaderProperties;

    // The base set of items that needs to be set. 
    public AMQMessageDelegate_0_8(BasicContentHeaderProperties properties, long deliveryTag)
    {
        super(deliveryTag);
        _contentHeaderProperties = properties;
        _readableProperties = (_contentHeaderProperties != null);
        _headerAdapter = new JMSHeaderAdapter(_readableProperties ? _contentHeaderProperties.getHeaders()
                                                                  : (new BasicContentHeaderProperties()).getHeaders() );
    }

    // Used for the creation of new messages
    protected AMQMessageDelegate_0_8()
    {
        this(new BasicContentHeaderProperties(), -1);
        _readableProperties = false;
        _headerAdapter = new JMSHeaderAdapter(_contentHeaderProperties.getHeaders());

    }

    // Used when generating a received message object
    protected AMQMessageDelegate_0_8(long deliveryTag,
                                     BasicContentHeaderProperties contentHeader,
                                     String exchange,
                                     String routingKey,
                                     AMQSession_0_8.DestinationCache<AMQQueue> queueDestinationCache,
                                     AMQSession_0_8.DestinationCache<AMQTopic> topicDestinationCache,
                                     int addressType)
    {
        this(contentHeader, deliveryTag);

        Integer type = contentHeader.getHeaders().getInteger(CustomJMSXProperty.JMS_QPID_DESTTYPE.getShortStringName());

        contentHeader.getHeaders().remove(QpidMessageProperties.QPID_NOT_VALID_BEFORE);

        AMQDestination dest = null;

        if(AMQDestination.getDefaultDestSyntax() == AMQDestination.DestSyntax.BURL)
        {
            // If we have a type set the attempt to use that.
            if (type != null)
            {
                switch (type.intValue())
                {
                    case AMQDestination.QUEUE_TYPE:
                        dest = queueDestinationCache.getDestination(exchange, routingKey);
                        break;
                    case AMQDestination.TOPIC_TYPE:
                        dest = topicDestinationCache.getDestination(exchange, routingKey);
                        break;
                    default:
                        // Use the generateDestination method
                        dest = null;
                }
            }

            if (dest == null)
            {
                dest = generateDestination(exchange, routingKey);
            }
        }
        else
        {
            String subject = null;
            if (contentHeader.getHeaders() != null
                && contentHeader.getHeaders().containsKey(QpidMessageProperties.QPID_SUBJECT))
            {
                subject = contentHeader.getHeaders().getString(QpidMessageProperties.QPID_SUBJECT);
            }
            if(type == null)
            {
                type = addressType;
            }
            dest = (AMQDestination) convertToAddressBasedDestination(exchange,
                                                                     routingKey, subject,
                                                                     true, type);
        }
        setJMSDestination(dest);
    }



    public String getJMSMessageID() throws JMSException
    {
        return getContentHeaderProperties().getMessageIdAsString();
    }

    public void setJMSMessageID(String messageId) throws JMSException
    {
        if (messageId != null)
        {
            getContentHeaderProperties().setMessageId(messageId);
        }
    }

    public void setJMSMessageID(UUID messageId) throws JMSException
    {
        if (messageId == null)
        {
            getContentHeaderProperties().setMessageId((String)null);
        }
        else
        {
            getContentHeaderProperties().setMessageId(asShortStringMsgId(messageId));
        }
    }

    private static final byte[] HEX_DIGITS = {0x30,0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39,
                                              0x61,0x62,0x63,0x64,0x65,0x66};

    private static AMQShortString asShortStringMsgId(UUID messageId)
    {
        long msb = messageId.getMostSignificantBits();
        long lsb = messageId.getLeastSignificantBits();

        byte[] messageIdBytes = new byte[39];
        messageIdBytes[0] = (byte) 'I';
        messageIdBytes[1] = (byte) 'D';
        messageIdBytes[2] = (byte) ':';

        messageIdBytes[3] = HEX_DIGITS[(int)((msb >> 60) & 0xFl)];
        messageIdBytes[4] = HEX_DIGITS[(int)((msb >> 56) & 0xFl)];
        messageIdBytes[5] = HEX_DIGITS[(int)((msb >> 52) & 0xFl)];
        messageIdBytes[6] = HEX_DIGITS[(int)((msb >> 48) & 0xFl)];
        messageIdBytes[7] = HEX_DIGITS[(int)((msb >> 44) & 0xFl)];
        messageIdBytes[8] = HEX_DIGITS[(int)((msb >> 40) & 0xFl)];
        messageIdBytes[9] = HEX_DIGITS[(int)((msb >> 36) & 0xFl)];
        messageIdBytes[10] = HEX_DIGITS[(int)((msb >> 32) & 0xFl)];

        messageIdBytes[11] = (byte) '-';
        messageIdBytes[12] = HEX_DIGITS[(int)((msb >> 28) & 0xFl)];
        messageIdBytes[13] = HEX_DIGITS[(int)((msb >> 24) & 0xFl)];
        messageIdBytes[14] = HEX_DIGITS[(int)((msb >> 20) & 0xFl)];
        messageIdBytes[15] = HEX_DIGITS[(int)((msb >> 16) & 0xFl)];
        messageIdBytes[16] = (byte) '-';
        messageIdBytes[17] = HEX_DIGITS[(int)((msb >> 12) & 0xFl)];
        messageIdBytes[18] = HEX_DIGITS[(int)((msb >> 8) & 0xFl)];
        messageIdBytes[19] = HEX_DIGITS[(int)((msb >> 4) & 0xFl)];
        messageIdBytes[20] = HEX_DIGITS[(int)(msb & 0xFl)];
        messageIdBytes[21] = (byte) '-';

        messageIdBytes[22] = HEX_DIGITS[(int)((lsb >> 60) & 0xFl)];
        messageIdBytes[23] = HEX_DIGITS[(int)((lsb >> 56) & 0xFl)];
        messageIdBytes[24] = HEX_DIGITS[(int)((lsb >> 52) & 0xFl)];
        messageIdBytes[25] = HEX_DIGITS[(int)((lsb >> 48) & 0xFl)];

        messageIdBytes[26] = (byte) '-';

        messageIdBytes[27] = HEX_DIGITS[(int)((lsb >> 44) & 0xFl)];
        messageIdBytes[28] = HEX_DIGITS[(int)((lsb >> 40) & 0xFl)];
        messageIdBytes[29] = HEX_DIGITS[(int)((lsb >> 36) & 0xFl)];
        messageIdBytes[30] = HEX_DIGITS[(int)((lsb >> 32) & 0xFl)];
        messageIdBytes[31] = HEX_DIGITS[(int)((lsb >> 28) & 0xFl)];
        messageIdBytes[32] = HEX_DIGITS[(int)((lsb >> 24) & 0xFl)];
        messageIdBytes[33] = HEX_DIGITS[(int)((lsb >> 20) & 0xFl)];
        messageIdBytes[34] = HEX_DIGITS[(int)((lsb >> 16) & 0xFl)];
        messageIdBytes[35] = HEX_DIGITS[(int)((lsb >> 12) & 0xFl)];
        messageIdBytes[36] = HEX_DIGITS[(int)((lsb >> 8) & 0xFl)];
        messageIdBytes[37] = HEX_DIGITS[(int)((lsb >> 4) & 0xFl)];
        messageIdBytes[38] = HEX_DIGITS[(int)(lsb & 0xFl)];

        return new AMQShortString(messageIdBytes);
    }

    public long getJMSTimestamp() throws JMSException
    {
        return getContentHeaderProperties().getTimestamp();
    }

    public void setJMSTimestamp(long timestamp) throws JMSException
    {
        getContentHeaderProperties().setTimestamp(timestamp);
    }

    public byte[] getJMSCorrelationIDAsBytes() throws JMSException
    {
        final AMQShortString correlationId = getContentHeaderProperties().getCorrelationId();
        return correlationId == null ? null : correlationId.getBytes();
    }

    public void setJMSCorrelationIDAsBytes(byte[] bytes) throws JMSException
    {
        getContentHeaderProperties().setCorrelationId(new AMQShortString(bytes));
    }

    public void setJMSCorrelationID(String correlationId) throws JMSException
    {
        getContentHeaderProperties().setCorrelationId(correlationId);
    }

    public String getJMSCorrelationID() throws JMSException
    {
        return getContentHeaderProperties().getCorrelationIdAsString();
    }

    public Destination getJMSReplyTo() throws JMSException
    {
        String replyToEncoding = getContentHeaderProperties().getReplyToAsString();
        if (replyToEncoding == null)
        {
            return null;
        }
        else
        {
            Destination dest = _destinationCache.get(replyToEncoding);
            if (dest == null)
            {
                try
                {
                    BindingURL binding = new AMQBindingURL(replyToEncoding);
                    dest = AMQDestination.createDestination(binding);
                }
                catch (URISyntaxException e)
                {
                    if(replyToEncoding.startsWith("/"))
                    {
                        dest = new DefaultRouterDestination(replyToEncoding);
                    }
                    else if(replyToEncoding.contains("/"))
                    {
                        String[] parts = replyToEncoding.split("/",2);
                        dest = new NonBURLReplyToDestination(ExchangeDefaults.DIRECT_EXCHANGE_CLASS, parts[0], parts[1]);
                    }
                    else
                    {
                        if (getAMQSession().isQueueBound(null, replyToEncoding, null))
                        {
                            dest = new NonBURLReplyToDestination(ExchangeDefaults.DIRECT_EXCHANGE_CLASS, "", replyToEncoding);
                        }
                        else if (isExchangeExist(replyToEncoding))
                        {
                            dest = new NonBURLReplyToDestination(ExchangeDefaults.DIRECT_EXCHANGE_CLASS, replyToEncoding, "");
                        }
                        else
                        {
                            dest = new DefaultRouterDestination(replyToEncoding);
                        }
                    }
                    
                }

                _destinationCache.put(replyToEncoding, dest);
            }

            return dest;
        }
    }

    private boolean isExchangeExist(final String replyToEncoding)
    {
        try
        {
            AMQDestination amqDestination = new AMQDestination()
            {
                @Override
                public String getAddressName()
                {
                    return replyToEncoding;
                }

                @Override
                public boolean isNameRequired()
                {
                    return false;
                }
            };
            return getAMQSession().isExchangeExist(amqDestination, false);
        }
        catch (Exception e)
        {
            return false;
        }
    }

    public void setJMSReplyTo(Destination destination) throws JMSException
    {
        if (destination == null)
        {
            getContentHeaderProperties().setReplyTo((String) null);
            return; // We're done here
        }

        if (!(destination instanceof AMQDestination))
        {
            throw new IllegalArgumentException(
                "ReplyTo destination may only be an AMQDestination - passed argument was type " + destination.getClass());
        }

        final AMQDestination amqd = (AMQDestination) destination;

        final AMQShortString encodedDestination = amqd.getEncodedName();
        _destinationCache.put(encodedDestination.toString(), destination);
        getContentHeaderProperties().setReplyTo(encodedDestination);
    }

    public Destination getJMSDestination()
    {
        return _destination;
    }

    public void setJMSDestination(Destination destination)
    {
        _destination = destination;
    }

    public void setContentType(String contentType)
    {
        getContentHeaderProperties().setContentType(contentType);
    }

    public String getContentType()
    {
        return getContentHeaderProperties().getContentTypeAsString();
    }

    public void setEncoding(String encoding)
    {
        getContentHeaderProperties().setEncoding(encoding);
    }

    public String getEncoding()
    {
        return getContentHeaderProperties().getEncodingAsString();
    }

    public String getReplyToString()
    {
        return getContentHeaderProperties().getReplyToAsString();
    }

    public int getJMSDeliveryMode() throws JMSException
    {
        return getContentHeaderProperties().getDeliveryMode();
    }

    public void setJMSDeliveryMode(int i) throws JMSException
    {
        getContentHeaderProperties().setDeliveryMode((byte) i);
    }

    public BasicContentHeaderProperties getContentHeaderProperties()
    {
        return _contentHeaderProperties;
    }


    public String getJMSType() throws JMSException
    {
        return getContentHeaderProperties().getTypeAsString();
    }

    public void setJMSType(String string) throws JMSException
    {
        getContentHeaderProperties().setType(string);
    }

    public long getJMSExpiration() throws JMSException
    {
        return getContentHeaderProperties().getExpiration();
    }

    public void setJMSExpiration(long l) throws JMSException
    {
        getContentHeaderProperties().setExpiration(l);
    }



    public boolean propertyExists(String propertyName) throws JMSException
    {
        return getJmsHeaders().propertyExists(propertyName);
    }

    public boolean getBooleanProperty(String propertyName) throws JMSException
    {
        if (STRICT_AMQP_COMPLIANCE)
        {
            throw new UnsupportedOperationException("JMS Properties not supported in AMQP");
        }

        return getJmsHeaders().getBoolean(propertyName);
    }

    public byte getByteProperty(String propertyName) throws JMSException
    {
        if (STRICT_AMQP_COMPLIANCE)
        {
            throw new UnsupportedOperationException("JMS Properties not supported in AMQP");
        }

        return getJmsHeaders().getByte(propertyName);
    }

    public short getShortProperty(String propertyName) throws JMSException
    {
        if (STRICT_AMQP_COMPLIANCE)
        {
            throw new UnsupportedOperationException("JMS Properties not supported in AMQP");
        }

        return getJmsHeaders().getShort(propertyName);
    }

    public int getIntProperty(String propertyName) throws JMSException
    {
        if (STRICT_AMQP_COMPLIANCE)
        {
            throw new UnsupportedOperationException("JMS Properties not supported in AMQP");
        }

        return getJmsHeaders().getInteger(propertyName);
    }

    public long getLongProperty(String propertyName) throws JMSException
    {
        if (STRICT_AMQP_COMPLIANCE)
        {
            throw new UnsupportedOperationException("JMS Properties not supported in AMQP");
        }

        return getJmsHeaders().getLong(propertyName);
    }

    public float getFloatProperty(String propertyName) throws JMSException
    {
        if (STRICT_AMQP_COMPLIANCE)
        {
            throw new UnsupportedOperationException("JMS Properties not supported in AMQP");
        }

        return getJmsHeaders().getFloat(propertyName);
    }

    public double getDoubleProperty(String propertyName) throws JMSException
    {
        if (STRICT_AMQP_COMPLIANCE)
        {
            throw new UnsupportedOperationException("JMS Properties not supported in AMQP");
        }

        return getJmsHeaders().getDouble(propertyName);
    }

    public String getStringProperty(String propertyName) throws JMSException
    {
        //NOTE: if the JMSX Property is a non AMQP property then we must check _strictAMQP and throw as below.
        if (propertyName.equals(CustomJMSXProperty.JMSXUserID.toString()))
        {
            return _contentHeaderProperties.getUserIdAsString();
        }
        else
        {
            if (STRICT_AMQP_COMPLIANCE)
            {
                throw new UnsupportedOperationException("JMS Properties not supported in AMQP");
            }

            return getJmsHeaders().getString(propertyName);
        }
    }

    public Object getObjectProperty(String propertyName) throws JMSException
    {
        return getJmsHeaders().getObject(propertyName);
    }

    public Enumeration getPropertyNames() throws JMSException
    {
        Set<String> keys = getJmsHeaders().getPropertyNames();
        return Collections.enumeration(keys);
    }

    public void setBooleanProperty(String propertyName, boolean b) throws JMSException
    {
        if (STRICT_AMQP_COMPLIANCE)
        {
            throw new UnsupportedOperationException("JMS Properties not supported in AMQP");
        }

        checkWritableProperties();
        getJmsHeaders().setBoolean(propertyName, b);
    }

    public void setByteProperty(String propertyName, byte b) throws JMSException
    {
        if (STRICT_AMQP_COMPLIANCE)
        {
            throw new UnsupportedOperationException("JMS Properties not supported in AMQP");
        }

        checkWritableProperties();
        getJmsHeaders().setByte(propertyName, b);
    }

    public void setShortProperty(String propertyName, short i) throws JMSException
    {
        if (STRICT_AMQP_COMPLIANCE)
        {
            throw new UnsupportedOperationException("JMS Properties not supported in AMQP");
        }

        checkWritableProperties();
        getJmsHeaders().setShort(propertyName, i);
    }

    public void setIntProperty(String propertyName, int i) throws JMSException
    {
        checkWritableProperties();
        getJmsHeaders().setInteger(propertyName, i);
    }

    public void setLongProperty(String propertyName, long l) throws JMSException
    {
        if (STRICT_AMQP_COMPLIANCE)
        {
            throw new UnsupportedOperationException("JMS Properties not supported in AMQP");
        }

        checkWritableProperties();
        getJmsHeaders().setLong(propertyName, l);
    }

    public void setFloatProperty(String propertyName, float f) throws JMSException
    {
        if (STRICT_AMQP_COMPLIANCE)
        {
            throw new UnsupportedOperationException("JMS Properties not supported in AMQP");
        }

        checkWritableProperties();
        getJmsHeaders().setFloat(propertyName, f);
    }

    public void setDoubleProperty(String propertyName, double v) throws JMSException
    {
        if (STRICT_AMQP_COMPLIANCE)
        {
            throw new UnsupportedOperationException("JMS Properties not supported in AMQP");
        }

        checkWritableProperties();
        getJmsHeaders().setDouble(propertyName, v);
    }

    public void setStringProperty(String propertyName, String value) throws JMSException
    {
        checkWritableProperties();
        getJmsHeaders().setString(propertyName, value);
    }

    public void setObjectProperty(String propertyName, Object object) throws JMSException
    {
        checkWritableProperties();
        getJmsHeaders().setObject(propertyName, object);
    }

    public void removeProperty(String propertyName) throws JMSException
    {
        getJmsHeaders().remove(propertyName);
    }


    private JMSHeaderAdapter getJmsHeaders()
    {
        return _headerAdapter;
    }

    protected void checkWritableProperties() throws MessageNotWriteableException
    {
        if (_readableProperties)
        {
            throw new MessageNotWriteableException("You need to call clearProperties() to make the message writable");
        }
    }


    public int getJMSPriority() throws JMSException
    {
        return getContentHeaderProperties().getPriority();
    }

    public void setJMSPriority(int i) throws JMSException
    {
        getContentHeaderProperties().setPriority((byte) i);
    }

    public void clearProperties() throws JMSException
    {
        getJmsHeaders().clear();

        _readableProperties = false;
    }

    @Override
    Object getProperty(final String name)
    {
        return getContentHeaderProperties().getHeaders().get(name);
    }

    @Override
    boolean hasProperty(final String name)
    {
        return getContentHeaderProperties().getHeaders().containsKey(name);
    }

    private static class DefaultRouterDestination extends AMQDestination implements Queue
    {
        private static final long serialVersionUID = -5042408431861384536L;

        // For Externalizable contract
        public DefaultRouterDestination()
        {
        }

        public DefaultRouterDestination(final String replyToEncoding)
        {
            super("",
                  ExchangeDefaults.DIRECT_EXCHANGE_CLASS,
                  replyToEncoding,
                  replyToEncoding);
        }

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

        @Override
        public boolean neverDeclare()
        {
            return true;
        }
    }

    private static class NonBURLReplyToDestination extends AMQDestination implements Queue
    {
        private static final long serialVersionUID = 122897705932489259L;

        // For Externalizable contract
        public NonBURLReplyToDestination()
        {
        }

        public NonBURLReplyToDestination(final String exchangeClass,
                                         final String exchange,
                                         final String routingKey)
        {
            super(exchange,
                  exchangeClass,
                  routingKey,
                  routingKey);
        }

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

        @Override
        public boolean neverDeclare()
        {
            return true;
        }
    }
}
