/*
   * Deploy a new channel, send messages, assert
   * that:
   * - The message was stored in the database
   * - The MessageResponse returned is not null
   * - The response is null
   * - The source connector response was not stored
   *
   * Call storeMessageResponse using a null MessageResponse assert:
   * - The source connector response was not stored
   *
   * Call storeMessageResponse using the returned MessageResponse, assert:
   * - The source connector response was not stored
   *
   * Modify the MessageResponse, creating/setting a new Response object
   * Call storeMessageResponse using the returned MessageResponse, assert:
   * - The source connector response was stored
   */
  @Test
  public final void testStoreMessageResponse() throws Exception {
    TestChannel channel = (TestChannel) TestUtils.createDefaultChannel(channelId, serverId);

    TestSourceConnector sourceConnector = (TestSourceConnector) channel.getSourceConnector();
    sourceConnector.setRespondAfterProcessing(true);
    channel
        .getResponseSelector()
        .setRespondFromName(ResponseConnectorProperties.RESPONSE_SOURCE_TRANSFORMED);

    channel.deploy();
    channel.start();

    for (int i = 1; i <= TEST_SIZE; i++) {
      RawMessage rawMessage = new RawMessage(testMessage);
      DispatchResult dispatchResult = null;

      try {
        dispatchResult = sourceConnector.dispatchRawMessage(rawMessage);

        if (dispatchResult.getSelectedResponse() != null) {
          dispatchResult.getSelectedResponse().setMessage("response");
        }
      } finally {
        sourceConnector.finishDispatch(dispatchResult, true, null);
      }

      if (dispatchResult != null) {
        sourceConnector.getMessageIds().add(dispatchResult.getMessageId());
      }

      // Assert that the message was created
      Message message = new Message();
      message.setChannelId(channel.getChannelId());
      message.setMessageId(dispatchResult.getMessageId());
      message.setServerId(channel.getServerId());
      message.setProcessed(true);
      TestUtils.assertMessageExists(message, false);

      // Assert that the message response is not null
      assertNotNull(dispatchResult);

      // Assert that the response is not null
      assertNotNull(dispatchResult.getSelectedResponse());

      // Assert that the source connector response was created
      TestUtils.assertResponseExists(channel.getChannelId(), dispatchResult.getMessageId());
    }

    channel.stop();
    channel.undeploy();

    ChannelController.getInstance().removeChannel(channel.getChannelId());
  }
  /*
   * Deploy a new channel, assert that:
   * - The default behaviour for the source connector is to wait for
   * destinations
   *
   * Send messages that should immediately process, assert that:
   * - The message was created and marked as processed in the database
   * - The MessageResponse returned is not null
   * - The response status is correct (TRANSFORMED)
   * - The channel's final transaction was created
   * - The source connector response was stored
   *
   * Send messages that should immediately queue, assert that:
   * - The message was stored in the database
   * - The MessageResponse returned is not null
   * - The response is not null
   * - The source connector response was not stored
   */
  @Test
  public final void testHandleRawMessage() throws Exception {
    TestChannel channel = (TestChannel) TestUtils.createDefaultChannel(channelId, serverId);
    TestSourceConnector sourceConnector = (TestSourceConnector) channel.getSourceConnector();
    sourceConnector.setRespondAfterProcessing(true);
    channel
        .getResponseSelector()
        .setRespondFromName(ResponseConnectorProperties.RESPONSE_SOURCE_TRANSFORMED);

    channel.deploy();
    channel.start();

    // Assert that the default source connector behaviour is to wait for destinations
    assertTrue(sourceConnector.isRespondAfterProcessing());

    // Send messages that immediately process
    for (int i = 1; i <= TEST_SIZE; i++) {
      RawMessage rawMessage = new RawMessage(testMessage);
      DispatchResult dispatchResult = null;

      try {
        dispatchResult = sourceConnector.dispatchRawMessage(rawMessage);

        if (dispatchResult.getSelectedResponse() != null) {
          dispatchResult.getSelectedResponse().setMessage("response");
        }
      } finally {
        sourceConnector.finishDispatch(dispatchResult, true, null);
      }

      if (dispatchResult != null) {
        sourceConnector.getMessageIds().add(dispatchResult.getMessageId());
      }

      // Assert that the message was created and processed
      Message message = new Message();
      message.setChannelId(channel.getChannelId());
      message.setMessageId(dispatchResult.getMessageId());
      message.setServerId(channel.getServerId());
      message.setProcessed(true);
      TestUtils.assertMessageExists(message, false);

      // Assert that the message response is not null
      assertNotNull(dispatchResult);
      // Assert that the response is not null
      assertNotNull(dispatchResult.getSelectedResponse());
      // Assert that the response status is correct
      assertEquals(Status.TRANSFORMED, dispatchResult.getSelectedResponse().getStatus());
      // Assert that the source connector response was created
      TestUtils.assertResponseExists(channel.getChannelId(), dispatchResult.getMessageId());
    }

    // Send messages that queue
    sourceConnector.setRespondAfterProcessing(false);
    channel.getResponseSelector().setRespondFromName(null);

    for (int i = 1; i <= TEST_SIZE; i++) {
      RawMessage rawMessage = new RawMessage(testMessage);
      DispatchResult dispatchResult = null;

      try {
        dispatchResult = sourceConnector.dispatchRawMessage(rawMessage);
      } finally {
        sourceConnector.finishDispatch(dispatchResult);
      }

      if (dispatchResult != null) {
        sourceConnector.getMessageIds().add(dispatchResult.getMessageId());
      }

      // Assert that the message was created
      Message message = new Message();
      message.setChannelId(channel.getChannelId());
      message.setMessageId(dispatchResult.getMessageId());
      message.setServerId(channel.getServerId());
      message.setProcessed(false);
      try {
        TestUtils.assertMessageExists(message, false);
      } catch (Exception e) {
        message.setProcessed(true);
        TestUtils.assertMessageExists(message, false);
      }

      // Assert that the message response is not null
      assertNotNull(dispatchResult);
      // Assert that the response is null
      assertNull(dispatchResult.getSelectedResponse());
      // Assert that the source connector response was not created
      TestUtils.assertResponseDoesNotExist(channel.getChannelId(), dispatchResult.getMessageId());
    }

    channel.stop();
    channel.undeploy();

    ChannelController.getInstance().removeChannel(channel.getChannelId());
  }