/*
 * 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.activemq.artemis.tests.integration.amqp;


import org.apache.activemq.artemis.api.core.JsonUtil;
import org.apache.activemq.artemis.api.core.RoutingType;
import org.apache.activemq.artemis.api.core.SimpleString;
import org.apache.activemq.artemis.api.core.management.QueueControl;
import org.apache.activemq.artemis.tests.integration.management.ManagementControlHelper;
import org.apache.activemq.transport.amqp.client.AmqpClient;
import org.apache.activemq.transport.amqp.client.AmqpConnection;
import org.apache.activemq.transport.amqp.client.AmqpMessage;
import org.apache.activemq.transport.amqp.client.AmqpSender;
import org.apache.activemq.transport.amqp.client.AmqpSession;
import org.apache.qpid.proton.amqp.Binary;
import org.apache.qpid.proton.amqp.Decimal128;
import org.apache.qpid.proton.amqp.Decimal32;
import org.apache.qpid.proton.amqp.Decimal64;
import org.junit.Assert;
import org.junit.Test;

import javax.jms.Connection;
import javax.jms.MessageConsumer;
import javax.jms.MessageProducer;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.json.JsonObject;
import java.math.BigDecimal;
import java.util.Map;
import java.util.UUID;

public class JMXManagementTest extends JMSClientTestSupport {

   @Test
   public void testListDeliveringMessages() throws Exception {
      SimpleString queue = new SimpleString(getQueueName());

      Connection connection1 = createConnection();
      Connection connection2 = createConnection();
      Session prodSession = connection1.createSession(false, Session.AUTO_ACKNOWLEDGE);
      Session consSession = connection2.createSession(true, Session.SESSION_TRANSACTED);

      javax.jms.Queue jmsQueue = prodSession.createQueue(queue.toString());

      QueueControl queueControl = createManagementControl(queue, queue);

      MessageProducer producer = prodSession.createProducer(jmsQueue);
      final int num = 20;

      for (int i = 0; i < num; i++) {
         TextMessage message = prodSession.createTextMessage("hello" + i);
         producer.send(message);
      }

      connection2.start();
      MessageConsumer consumer = consSession.createConsumer(jmsQueue);

      for (int i = 0; i < num; i++) {
         TextMessage msgRec = (TextMessage) consumer.receive(5000);
         assertNotNull(msgRec);
         assertEquals(msgRec.getText(), "hello" + i);
      }

      //before commit
      assertEquals(num, queueControl.getDeliveringCount());

      Map<String, Map<String, Object>[]> result = queueControl.listDeliveringMessages();
      assertEquals(1, result.size());

      Map<String, Object>[] msgMaps = result.entrySet().iterator().next().getValue();

      assertEquals(num, msgMaps.length);

      consSession.commit();
      result = queueControl.listDeliveringMessages();

      assertEquals(0, result.size());

      consSession.close();
      prodSession.close();

      connection1.close();
      connection2.close();
   }

   @Test
   public void testGetFirstMessage() throws Exception {
      AmqpClient client = createAmqpClient();
      AmqpConnection connection = addConnection(client.connect());

      try {
         AmqpSession session = connection.createSession();
         AmqpSender sender = session.createSender(getQueueName());

         session.begin();
         AmqpMessage message = new AmqpMessage();
         message.setApplicationProperty("TEST_BINARY", new Binary("TEST".getBytes()));
         message.setApplicationProperty("TEST_STRING", "TEST");
         message.setText("TEST");
         sender.send(message);
         session.commit();

         SimpleString queue = new SimpleString(getQueueName());
         QueueControl queueControl = createManagementControl(queue, queue);
         String firstMessageAsJSON = queueControl.getFirstMessageAsJSON();
         Assert.assertNotNull(firstMessageAsJSON);
      } finally {
         connection.close();
      }
   }

   @Test
   public void testGetFirstMessageWithAMQPTypes() throws Exception {
      AmqpClient client = createAmqpClient();
      AmqpConnection connection = addConnection(client.connect());

      try {
         UUID uuid = UUID.randomUUID();
         Character character = new Character('C');
         AmqpSession session = connection.createSession();
         AmqpSender sender = session.createSender(getQueueName());

         session.begin();
         AmqpMessage message = new AmqpMessage();
         message.setApplicationProperty("TEST_UUID", uuid);
         message.setApplicationProperty("TEST_CHAR", character);
         message.setApplicationProperty("TEST_DECIMAL_32", new Decimal32(BigDecimal.ONE));
         message.setApplicationProperty("TEST_DECIMAL_64", new Decimal64(BigDecimal.ONE));
         message.setApplicationProperty("TEST_DECIMAL_128", new Decimal128(BigDecimal.ONE));

         sender.send(message);
         session.commit();

         SimpleString queue = new SimpleString(getQueueName());
         QueueControl queueControl = createManagementControl(queue, queue);
         String firstMessageAsJSON = queueControl.getFirstMessageAsJSON();
         Assert.assertNotNull(firstMessageAsJSON);

         JsonObject firstMessageObject = JsonUtil.readJsonArray(firstMessageAsJSON).getJsonObject(0);

         Assert.assertEquals(uuid.toString(), firstMessageObject.getString("TEST_UUID"));
         Assert.assertEquals(character.toString(), firstMessageObject.getString("TEST_CHAR"));
         Assert.assertNotNull(firstMessageObject.getJsonNumber("TEST_DECIMAL_32"));
         Assert.assertNotNull(firstMessageObject.getJsonNumber("TEST_DECIMAL_64"));
         Assert.assertNotNull(firstMessageObject.getJsonNumber("TEST_DECIMAL_128"));
      } finally {
         connection.close();
      }
   }

   protected QueueControl createManagementControl(final SimpleString address,
                                                  final SimpleString queue) throws Exception {
      QueueControl queueControl = ManagementControlHelper.createQueueControl(address, queue, RoutingType.ANYCAST, this.mBeanServer);

      return queueControl;
   }
}
