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

using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using Amqp.Framing;
using Amqp.Types;
using Apache.NMS;
using Apache.NMS.AMQP.Provider.Amqp.Message;
using Apache.NMS.AMQP.Util;
using NUnit.Framework;

namespace NMS.AMQP.Test.Provider.Amqp
{
    [TestFixture]
    public class AmqpNmsObjectMessageFacadeTest : AmqpNmsMessageTypesTestCase
    {
        // ---------- Test initial state of newly created message -----------------//

        [Test]
        public void TestNewMessageToSendDoesNotContainMessageTypeAnnotation()
        {
            AmqpNmsObjectMessageFacade amqpObjectMessageFacade = CreateNewObjectMessageFacade(false);
            Assert.Null(amqpObjectMessageFacade.MessageAnnotations);

            Assert.AreEqual(MessageSupport.JMS_TYPE_OBJ, amqpObjectMessageFacade.JmsMsgType);
        }

        [Test]
        public void TestNewMessageToSendReturnsNullObject()
        {
            DoNewMessageToSendReturnsNullObjectTestImpl(false);
        }

        [Test]
        public void TestNewAmqpTypedMessageToSendReturnsNullObject()
        {
            DoNewMessageToSendReturnsNullObjectTestImpl(true);
        }

        private void DoNewMessageToSendReturnsNullObjectTestImpl(bool amqpTyped)
        {
            AmqpNmsObjectMessageFacade amqpObjectMessageFacade = CreateNewObjectMessageFacade(amqpTyped);
            Assert.Null(amqpObjectMessageFacade.Body);
        }

        [Test]
        public void TestNewMessageToSendHasBodySectionRepresentingNull()
        {
            DoNewMessageToSendHasBodySectionRepresentingNull(false);
        }

        [Test]
        public void TestNewAmqpTypedMessageToSendHasBodySectionRepresentingNull()
        {
            DoNewMessageToSendHasBodySectionRepresentingNull(true);
        }

        private void DoNewMessageToSendHasBodySectionRepresentingNull(bool amqpTyped)
        {
            AmqpNmsObjectMessageFacade amqpObjectMessageFacade = CreateNewObjectMessageFacade(amqpTyped);
            amqpObjectMessageFacade.OnSend(TimeSpan.Zero);

            Assert.NotNull(amqpObjectMessageFacade.Message.BodySection, "Message body should be presents");
            if (amqpTyped)
                Assert.AreSame(AmqpTypedObjectDelegate.NULL_OBJECT_BODY, amqpObjectMessageFacade.Message.BodySection, "Expected existing body section to be replaced");
            else
                Assert.AreSame(AmqpSerializedObjectDelegate.NULL_OBJECT_BODY, amqpObjectMessageFacade.Message.BodySection, "Expected existing body section to be replaced");
        }

        // ---------- test for normal message operations -------------------------//

        /*
         * Test that Bytes setting an object on a new message results in the expected
         * content in the body section of the underlying message.
         */
        [Test]
        public void TestSetObjectOnNewMessage()
        {
            String content = "myStringContent";

            AmqpNmsObjectMessageFacade amqpObjectMessageFacade = CreateNewObjectMessageFacade();
            amqpObjectMessageFacade.Body = content;

            var bytes = GetSerializedBytes(content);

            // retrieve the bytes from the underlying message, check they match expectation
            RestrictedDescribed messageBodySection = amqpObjectMessageFacade.Message.BodySection;
            Assert.NotNull(messageBodySection);

            Assert.IsInstanceOf<Data>(messageBodySection);
            CollectionAssert.AreEqual(bytes, ((Data) messageBodySection).Binary, "Underlying message data section did not contain the expected bytes");
        }

        /*
         * Test that setting an object on a new message results in the expected
         * content in the body section of the underlying message.
         */
        [Test]
        public void TestSetObjectOnNewAmqpTypedMessage()
        {
            String content = "myStringContent";

            AmqpNmsObjectMessageFacade amqpObjectMessageFacade = CreateNewObjectMessageFacade(true);
            amqpObjectMessageFacade.Body = content;

            // retrieve the body from the underlying message, check it matches expectation
            RestrictedDescribed section = amqpObjectMessageFacade.Message.BodySection;
            Assert.NotNull(section);
            Assert.IsInstanceOf<AmqpValue>(section);
            Assert.AreEqual(content, ((AmqpValue) section).Value);
        }

        /*
         * Test that setting a null object on a message results in the underlying body
         * section being set with the null object body, ensuring getObject returns null.
         */
        [Test]
        public void TestSetObjectWithNullClearsExistingBodySection()
        {
            global::Amqp.Message message = new global::Amqp.Message
            {
                Properties = new Properties
                {
                    ContentType = MessageSupport.SERIALIZED_DOTNET_OBJECT_CONTENT_TYPE
                },
                BodySection = new Data
                {
                    Binary = new byte[0]
                }
            };

            AmqpNmsObjectMessageFacade facade = CreateReceivedObjectMessageFacade(message);

            Assert.NotNull(facade.Message.BodySection, "Expected existing body section to be found");
            facade.Body = null;
            Assert.AreSame(AmqpSerializedObjectDelegate.NULL_OBJECT_BODY, facade.Message.BodySection, "Expected existing body section to be replaced");
            Assert.Null(facade.Body);
        }

        /*
         * Test that clearing the body on a message results in the underlying body
         * section being set with the null object body, ensuring getObject returns null.
         */
        [Test]
        public void TestClearBodyWithExistingSerializedBodySection()
        {
            global::Amqp.Message message = new global::Amqp.Message
            {
                Properties = new Properties
                {
                    ContentType = MessageSupport.SERIALIZED_DOTNET_OBJECT_CONTENT_TYPE
                },
                BodySection = new Data
                {
                    Binary = new byte[0]
                }
            };

            AmqpNmsObjectMessageFacade facade = CreateReceivedObjectMessageFacade(message);

            Assert.NotNull(facade.Message.BodySection, "Expected existing body section to be found");
            facade.ClearBody();

            Assert.AreSame(AmqpSerializedObjectDelegate.NULL_OBJECT_BODY, facade.Message.BodySection, "Expected existing body section to be replaced");
            Assert.Null(facade.Body);
        }

        /*
         * Test that setting an object on a new message and later getting the value, returns an
         * equal but different object that does not pick up intermediate changes to the set object.
         */
        [Test]
        public void TestSetThenGetObjectOnSerializedMessageReturnsSnapshot()
        {
            Dictionary<string, string> origMap = new Dictionary<string, string>
            {
                {"key1", "value1"}
            };

            AmqpNmsObjectMessageFacade facade = CreateNewObjectMessageFacade(false);
            facade.Body = origMap;

            Dictionary<string, string> d = new Dictionary<string, string>();

            // verify we get a different-but-equal object back
            object body = facade.Body;
            Assert.IsInstanceOf<Dictionary<string, string>>(body);
            Dictionary<string, string> returnedObject1 = (Dictionary<string, string>) body;
            Assert.AreNotSame(origMap, returnedObject1, "Expected different objects, due to snapshot being taken");
            Assert.AreEqual(origMap, returnedObject1, "Expected equal objects, due to snapshot being taken");

            // mutate the original object
            origMap.Add("key2", "value2");

            // verify we get a different-but-equal object back when compared to the previously retrieved object
            object body2 = facade.Body;
            Assert.IsInstanceOf<Dictionary<string, string>>(body2);
            Dictionary<string, string> returnedObject2 = (Dictionary<string, string>) body2;
            Assert.AreNotSame(origMap, returnedObject2, "Expected different objects, due to snapshot being taken");
            Assert.AreEqual(returnedObject1, returnedObject2);

            // verify the mutated map is a different and not equal object
            Assert.AreNotSame(returnedObject1, returnedObject2, "Expected different objects, due to snapshot being taken");
            Assert.AreNotEqual(origMap, returnedObject2, "Expected objects to differ, due to snapshot being taken");
        }

        // ---------- test handling of received messages -------------------------//

        [Test]
        public void TestGetObjectUsingReceivedMessageWithNoBodySectionNoContentTypeReturnsNull()
        {
            DoGetObjectUsingReceivedMessageWithNoBodySectionReturnsNullTestImpl(true);
        }

        [Test]
        public void TestGetObjectUsingReceivedMessageWithNoBodySectionReturnsNull()
        {
            DoGetObjectUsingReceivedMessageWithNoBodySectionReturnsNullTestImpl(false);
        }

        private void DoGetObjectUsingReceivedMessageWithNoBodySectionReturnsNullTestImpl(bool amqpTyped)
        {
            global::Amqp.Message message = new global::Amqp.Message();

            if (!amqpTyped)
            {
                message.Properties = new Properties {ContentType = MessageSupport.SERIALIZED_DOTNET_OBJECT_CONTENT_TYPE};
            }

            AmqpNmsObjectMessageFacade facade = CreateReceivedObjectMessageFacade(message);

            Assert.Null(facade.Body, "Expected null object");
        }

        [Test]
        public void TestGetObjectUsingReceivedMessageWithDataSectionContainingNothingReturnsNull()
        {
            global::Amqp.Message message = new global::Amqp.Message
            {
                Properties = new Properties
                {
                    ContentType = MessageSupport.SERIALIZED_DOTNET_OBJECT_CONTENT_TYPE
                },
                BodySection = new AmqpValue {Value = "nonBinarySectionContent"}
            };

            AmqpNmsObjectMessageFacade facade = CreateReceivedObjectMessageFacade(message);

            Assert.Catch<IllegalStateException>(() =>
            {
                object body = facade.Body;
            });
        }

        /*
         * Test that setting an object on a received message and later getting the value, returns an
         * equal but different object that does not pick up intermediate changes to the set object.
         */
        [Test]
        public void TestSetThenGetObjectOnSerializedReceivedMessageNoContentTypeReturnsSnapshot()
        {
            Dictionary<string, string> origMap = new Dictionary<string, string>
            {
                {"key1", "value1"}
            };
            global::Amqp.Message message = new global::Amqp.Message()
            {
                Properties = new Properties {ContentType = MessageSupport.SERIALIZED_DOTNET_OBJECT_CONTENT_TYPE},
                BodySection = new Data {Binary = GetSerializedBytes(origMap)}
            };

            AmqpNmsObjectMessageFacade facade = CreateReceivedObjectMessageFacade(message);

            // verify we get a different-but-equal object back
            object body = facade.Body;
            Assert.IsInstanceOf<Dictionary<string, string>>(body);
            Dictionary<string, string> returnedObject1 = (Dictionary<string, string>) body;
            Assert.AreNotSame(origMap, returnedObject1, "Expected different objects, due to snapshot being taken");
            Assert.AreEqual(origMap, returnedObject1, "Expected equal objects, due to snapshot being taken");


            // verify we get a different-but-equal object back when compared to the previously retrieved object
            object body2 = facade.Body;
            Assert.IsInstanceOf<Dictionary<string, string>>(body2);
            Dictionary<string, string> returnedObject2 = (Dictionary<string, string>) body2;
            Assert.AreNotSame(origMap, returnedObject2, "Expected different objects, due to snapshot being taken");
            Assert.AreEqual(returnedObject1, returnedObject2);

            // mutate the original object
            origMap.Add("key2", "value2");

            // verify the mutated map is a different and not equal object
            Assert.AreNotSame(returnedObject1, returnedObject2, "Expected different objects, due to snapshot being taken");
            Assert.AreNotEqual(origMap, returnedObject2, "Expected objects to differ, due to snapshot being taken");
        }

        [Test]
        public void TestSetThenGetObjectOnSerializedReceivedMessageReturnsSnapshot()
        {
            Map origMap = new Map
            {
                {"key1", "value1"}
            };
            global::Amqp.Message message = new global::Amqp.Message {BodySection = new AmqpValue {Value = origMap}};

            AmqpNmsObjectMessageFacade facade = CreateReceivedObjectMessageFacade(message);

            // verify we get a different-but-equal object back
            object body = facade.Body;
            Assert.IsInstanceOf<Map>(body);
            Map returnedObject1 = (Map) body;
            Assert.AreNotSame(origMap, returnedObject1, "Expected different objects, due to snapshot being taken");
            Assert.AreEqual(origMap, returnedObject1, "Expected equal objects, due to snapshot being taken");


            // verify we get a different-but-equal object back when compared to the previously retrieved object
            object body2 = facade.Body;
            Assert.IsInstanceOf<Map>(body2);
            Map returnedObject2 = (Map) body2;
            Assert.AreNotSame(origMap, returnedObject2, "Expected different objects, due to snapshot being taken");
            Assert.AreEqual(returnedObject1, returnedObject2);

            // mutate the original object
            origMap.Add("key2", "value2");

            // verify the mutated map is a different and not equal object
            Assert.AreNotSame(returnedObject1, returnedObject2, "Expected different objects, due to snapshot being taken");
            Assert.AreNotEqual(origMap, returnedObject2, "Expected objects to differ, due to snapshot being taken");
        }

        [Test]
        public void TestMessageCopy()
        {
            String content = "myStringContent";

            AmqpNmsObjectMessageFacade amqpObjectMessageFacade = CreateNewObjectMessageFacade();
            amqpObjectMessageFacade.Body = content;

            AmqpNmsObjectMessageFacade copy = amqpObjectMessageFacade.Copy() as AmqpNmsObjectMessageFacade;
            Assert.IsNotNull(copy);
            Assert.AreEqual(amqpObjectMessageFacade.Body, copy.Body);
        }

        private static byte[] GetSerializedBytes(object content)
        {
            using (MemoryStream stream = new MemoryStream())
            {
                BinaryFormatter formatter = new BinaryFormatter();
                formatter.Serialize(stream, content);
                byte[] bytes = stream.ToArray();
                return bytes;
            }
        }
    }
}