// Copyright (C) 2013 The Android Open Source Project
//
// Licensed 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 com.googlesource.gerrit.plugins.its.base.workflow;

import static org.easymock.EasyMock.anyObject;
import static org.easymock.EasyMock.expect;

import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.google.gerrit.extensions.config.FactoryModule;
import com.google.gerrit.server.events.ChangeEvent;
import com.google.gerrit.server.events.Event;
import com.google.inject.Guice;
import com.google.inject.Injector;

import com.googlesource.gerrit.plugins.its.base.its.ItsConfig;
import com.googlesource.gerrit.plugins.its.base.testutil.LoggingMockingTestCase;
import com.googlesource.gerrit.plugins.its.base.util.PropertyExtractor;

import java.util.Collection;
import java.util.Collections;
import java.util.Set;

public class ActionControllerTest extends LoggingMockingTestCase {
  private Injector injector;

  private PropertyExtractor propertyExtractor;
  private RuleBase ruleBase;
  private ActionExecutor actionExecutor;
  private ItsConfig itsConfig;

  public void testNoPropertySets() {
    ActionController actionController = createActionController();

    ChangeEvent event = createMock(ChangeEvent.class);

    Set<Set<Property>> propertySets = Collections.emptySet();
    expect(propertyExtractor.extractFrom(event)).andReturn(propertySets)
        .anyTimes();

    replayMocks();

    actionController.onEvent(event);
  }

  public void testNoActions() {
    ActionController actionController = createActionController();

    ChangeEvent event = createMock(ChangeEvent.class);

    Set<Set<Property>> propertySets = Sets.newHashSet();
    Set<Property> propertySet = Collections.emptySet();
    propertySets.add(propertySet);

    expect(propertyExtractor.extractFrom(event)).andReturn(propertySets)
        .anyTimes();

    Collection<ActionRequest> actions = Collections.emptySet();
    expect(ruleBase.actionRequestsFor(propertySet)).andReturn(actions).once();

    replayMocks();

    actionController.onEvent(event);
  }

  public void testNoIssues() {
    ActionController actionController = createActionController();

    ChangeEvent event = createMock(ChangeEvent.class);

    Set<Set<Property>> propertySets = Sets.newHashSet();
    Set<Property> propertySet = Collections.emptySet();
    propertySets.add(propertySet);

    expect(propertyExtractor.extractFrom(event)).andReturn(propertySets)
        .anyTimes();

    Collection<ActionRequest> actions = Lists.newArrayListWithCapacity(1);
    ActionRequest action1 = createMock(ActionRequest.class);
    actions.add(action1);
    expect(ruleBase.actionRequestsFor(propertySet)).andReturn(actions).once();

    replayMocks();

    actionController.onEvent(event);
  }

  public void testSinglePropertySetSingleActionSingleIssue() {
    ActionController actionController = createActionController();

    ChangeEvent event = createMock(ChangeEvent.class);

    Property propertyIssue1 = createMock(Property.class);
    expect(propertyIssue1.getKey()).andReturn("issue").anyTimes();
    expect(propertyIssue1.getValue()).andReturn("testIssue").anyTimes();

    Set<Property> propertySet = Sets.newHashSet();
    propertySet.add(propertyIssue1);

    Set<Set<Property>> propertySets = Sets.newHashSet();
    propertySets.add(propertySet);

    expect(propertyExtractor.extractFrom(event)).andReturn(propertySets)
        .anyTimes();

    Collection<ActionRequest> actionRequests =
        Lists.newArrayListWithCapacity(1);
    ActionRequest actionRequest1 = createMock(ActionRequest.class);
    actionRequests.add(actionRequest1);
    expect(ruleBase.actionRequestsFor(propertySet)).andReturn(actionRequests)
        .once();

    actionExecutor.execute("testIssue", actionRequests, propertySet);

    replayMocks();

    actionController.onEvent(event);
  }

  public void testMultiplePropertySetsMultipleActionMultipleIssue() {
    ActionController actionController = createActionController();

    ChangeEvent event = createMock(ChangeEvent.class);

    Property propertyIssue1 = createMock(Property.class);
    expect(propertyIssue1.getKey()).andReturn("issue").anyTimes();
    expect(propertyIssue1.getValue()).andReturn("testIssue").anyTimes();

    Property propertyIssue2 = createMock(Property.class);
    expect(propertyIssue2.getKey()).andReturn("issue").anyTimes();
    expect(propertyIssue2.getValue()).andReturn("testIssue2").anyTimes();

    Set<Property> propertySet1 = Sets.newHashSet();
    propertySet1.add(propertyIssue1);

    Set<Property> propertySet2 = Sets.newHashSet();
    propertySet2.add(propertyIssue1);
    propertySet2.add(propertyIssue2);

    Set<Set<Property>> propertySets = Sets.newHashSet();
    propertySets.add(propertySet1);
    propertySets.add(propertySet2);

    expect(propertyExtractor.extractFrom(event)).andReturn(propertySets)
        .anyTimes();

    Collection<ActionRequest> actionRequests1 =
        Lists.newArrayListWithCapacity(1);
    ActionRequest actionRequest1 = createMock(ActionRequest.class);
    actionRequests1.add(actionRequest1);

    Collection<ActionRequest> actionRequests2 =
        Lists.newArrayListWithCapacity(2);
    ActionRequest actionRequest2 = createMock(ActionRequest.class);
    actionRequests2.add(actionRequest2);
    ActionRequest actionRequest3 = createMock(ActionRequest.class);
    actionRequests2.add(actionRequest3);

    expect(ruleBase.actionRequestsFor(propertySet1)).andReturn(actionRequests1)
        .once();
    expect(ruleBase.actionRequestsFor(propertySet2)).andReturn(actionRequests2)
        .once();

    actionExecutor.execute("testIssue", actionRequests1, propertySet1);
    actionExecutor.execute("testIssue", actionRequests2, propertySet2);
    actionExecutor.execute("testIssue2", actionRequests2, propertySet2);

    replayMocks();

    actionController.onEvent(event);
  }
  private ActionController createActionController() {
    return injector.getInstance(ActionController.class);
  }

  private void setupCommonMocks() {
    expect(itsConfig.isEnabled(anyObject(Event.class))).andReturn(true)
        .anyTimes();
  }

  @Override
  public void setUp() throws Exception {
    super.setUp();
    injector = Guice.createInjector(new TestModule());

    setupCommonMocks();
  }

  private class TestModule extends FactoryModule {
    @Override
    protected void configure() {
      propertyExtractor = createMock(PropertyExtractor.class);
      bind(PropertyExtractor.class).toInstance(propertyExtractor);

      ruleBase = createMock(RuleBase.class);
      bind(RuleBase.class).toInstance(ruleBase);

      actionExecutor = createMock(ActionExecutor.class);
      bind(ActionExecutor.class).toInstance(actionExecutor);

      itsConfig = createMock(ItsConfig.class);
      bind(ItsConfig.class).toInstance(itsConfig);
    }
  }
}