/*
 * 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.fineract.cn.command.internal;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.apache.fineract.cn.command.annotation.Aggregate;
import org.apache.fineract.cn.command.annotation.CommandHandler;
import org.apache.fineract.cn.command.domain.CommandHandlerHolder;
import org.apache.fineract.cn.command.domain.CommandProcessingException;
import org.apache.fineract.cn.command.fixture.DomainAggregate;
import org.apache.fineract.cn.command.fixture.DomainException;
import org.apache.fineract.cn.command.fixture.DomainObject;
import org.apache.fineract.cn.command.fixture.ErroneousDomainCommand;
import org.apache.fineract.cn.command.fixture.ReturningCommand;
import org.apache.fineract.cn.command.fixture.ReturningWithEventCommand;
import org.apache.fineract.cn.command.fixture.VoidCommand;
import org.apache.fineract.cn.command.fixture.VoidWithEventCommand;
import org.apache.fineract.cn.command.repository.CommandSource;
import org.apache.fineract.cn.command.util.CommandConstants;
import org.apache.fineract.cn.cassandra.core.TenantAwareEntityTemplate;
import org.junit.Assert;
import org.junit.Test;
import org.mockito.Mockito;
import org.slf4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.core.env.Environment;
import org.springframework.jms.core.JmsTemplate;
import org.springframework.jms.core.MessagePostProcessor;

import java.util.HashMap;
import java.util.concurrent.Future;

public class CommandBusTest {

  public CommandBusTest() {
    super();
  }

  private static TestHarness createTestHarness() {
    final Environment mockedEnvironment = Mockito.mock(Environment.class);
    Mockito.when(mockedEnvironment.getProperty(CommandConstants.APPLICATION_NAME_PROP,
        CommandConstants.APPLICATION_NAME_DEFAULT))
        .thenReturn(CommandConstants.APPLICATION_NAME_DEFAULT);

    final Logger mockedLogger = Mockito.mock(Logger.class);

    final Gson gson = new GsonBuilder().create();

    final TenantAwareEntityTemplate mockedTenantAwareEntityTemplate = Mockito.mock(TenantAwareEntityTemplate.class);

    final JmsTemplate mockedJmsTemplate = Mockito.mock(JmsTemplate.class);

    final ApplicationContext mockedApplicationContext = Mockito.mock(ApplicationContext.class);
    final HashMap<String, Object> mockedBeans = new HashMap<>();
    mockedBeans.put(DomainAggregate.class.getSimpleName(), new DomainAggregate());
    Mockito.when(mockedApplicationContext.getBeansWithAnnotation(Mockito.eq(Aggregate.class)))
        .thenReturn(mockedBeans);
    Mockito.when(mockedApplicationContext.getBean(Mockito.eq(DomainAggregate.class)))
        .thenReturn((DomainAggregate) mockedBeans.get(DomainAggregate.class.getSimpleName()));

    final CommandBus commandBus =
        new CommandBus(mockedEnvironment, mockedLogger, gson, mockedTenantAwareEntityTemplate, mockedJmsTemplate);
    commandBus.setApplicationContext(mockedApplicationContext);

    return new TestHarness(commandBus, mockedTenantAwareEntityTemplate, mockedJmsTemplate);
  }

  @Test
  public void shouldProcessVoidCommand() {
    final TestHarness testHarness = createTestHarness();
    testHarness.commandBus.dispatch(new VoidCommand());

    Mockito.verify(testHarness.mockedTenantAwareEntityTemplate, Mockito.times(2)).save(Mockito.any(CommandSource.class));
    Mockito.verify(testHarness.jmsTemplate, Mockito.times(0)).convertAndSend(Mockito.any(Object.class), Mockito.any(MessagePostProcessor.class));
  }

  @Test
  public void shouldProcessReturningCommand() throws Exception {
    final TestHarness testHarness = createTestHarness();
    final DomainObject domainObject = new DomainObject("test", 1L);

    final Future<DomainObject> future = testHarness.commandBus.dispatch(new ReturningCommand(domainObject), DomainObject.class);
    final DomainObject returnValue = future.get();

    Assert.assertNotNull(returnValue);
    Assert.assertEquals(domainObject.getStringProperty(), returnValue.getStringProperty());
    Assert.assertEquals(domainObject.getLongProperty(), returnValue.getLongProperty());

    Mockito.verify(testHarness.mockedTenantAwareEntityTemplate, Mockito.times(2)).save(Mockito.any(CommandSource.class));
    Mockito.verify(testHarness.jmsTemplate, Mockito.times(0)).convertAndSend(Mockito.any(Object.class), Mockito.any(MessagePostProcessor.class));
  }

  @Test
  public void shouldProcessVoidWithEventCommand() {
    final TestHarness testHarness = createTestHarness();
    testHarness.commandBus.dispatch(new VoidWithEventCommand());

    Mockito.verify(testHarness.mockedTenantAwareEntityTemplate, Mockito.times(2)).save(Mockito.any(CommandSource.class));
    Mockito.verify(testHarness.jmsTemplate, Mockito.times(1)).convertAndSend(Mockito.any(Object.class), Mockito.any(MessagePostProcessor.class));
  }

  @Test
  public void shouldProcessReturningWithEventCommand() throws Exception {
    final TestHarness testHarness = createTestHarness();
    final DomainObject domainObject = new DomainObject("test", 2L);

    final Future<DomainObject> future = testHarness.commandBus.dispatch(new ReturningWithEventCommand(domainObject), DomainObject.class);
    final DomainObject returnValue = future.get();

    Assert.assertNotNull(returnValue);
    Assert.assertEquals(domainObject.getStringProperty(), returnValue.getStringProperty());
    Assert.assertEquals(domainObject.getLongProperty(), returnValue.getLongProperty());

    Mockito.verify(testHarness.mockedTenantAwareEntityTemplate, Mockito.times(2)).save(Mockito.any(CommandSource.class));
    Mockito.verify(testHarness.jmsTemplate, Mockito.times(1)).convertAndSend(Mockito.any(Object.class), Mockito.any(MessagePostProcessor.class));
  }

  @Test
  public void shouldNotProcessCommandRethrowDeclaredException()
      throws CommandProcessingException {

    final TestHarness testHarness = createTestHarness();

    final ErroneousDomainCommand erroneousDomainCommand = new ErroneousDomainCommand();
    try {
      testHarness.commandBus.dispatch(erroneousDomainCommand, Void.class);
      Assert.fail();
    } catch (final DomainException ex) {
      // do nothing
    }

    Mockito.verify(testHarness.mockedTenantAwareEntityTemplate, Mockito.times(2)).save(Mockito.any(CommandSource.class));
  }

  @Test()
  public void getCommandHandlerMethodWithoutReturnValue() {
    final TestHarness testHarness = createTestHarness();
    final TestCommandHandler aggregateHandler = new TestCommandHandler();
    final CommandHandlerHolder commandHandlerHolder = testHarness.commandBus
        .getCommandHandlerMethodFromClass(TestCommandClass1.class, aggregateHandler);
    Assert.assertNotNull(commandHandlerHolder);
  }

  @Test()
  public void getCommandHandlerMethodWithReturnValue() {
    final TestHarness testHarness = createTestHarness();
    final TestCommandHandler aggregateHandler = new TestCommandHandler();
    final CommandHandlerHolder commandHandlerHolder = testHarness.commandBus
        .getCommandHandlerMethodFromClass(TestCommandClass2.class, aggregateHandler);
    Assert.assertNotNull(commandHandlerHolder);
  }

  private static class TestHarness {

    CommandBus commandBus;
    TenantAwareEntityTemplate mockedTenantAwareEntityTemplate;
    JmsTemplate jmsTemplate;

    private TestHarness(final CommandBus commandBus,
                        final TenantAwareEntityTemplate mockedTenantAwareEntityTemplate,
                        final JmsTemplate jmsTemplate) {
      this.commandBus = commandBus;
      this.mockedTenantAwareEntityTemplate = mockedTenantAwareEntityTemplate;
      this.jmsTemplate = jmsTemplate;
    }
  }

  private static class TestCommandClass1 {

  }

  private static class TestCommandClass2 {

  }

  private static class TestCommandResponse {

  }

  private static class TestCommandHandler {

    @SuppressWarnings("unused")
    @CommandHandler
    void process(final TestCommandClass1 command) {
    }

    @SuppressWarnings("unused")
    @CommandHandler
    TestCommandResponse process(final TestCommandClass2 command) {
      return new TestCommandResponse();
    }
  }
}
