// 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.action;

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

import com.google.common.collect.Sets;
import com.google.gerrit.extensions.config.FactoryModule;
import com.google.gerrit.server.config.SitePath;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.googlesource.gerrit.plugins.its.base.its.ItsFacade;
import com.googlesource.gerrit.plugins.its.base.testutil.LoggingMockingTestCase;
import com.googlesource.gerrit.plugins.its.base.workflow.ActionRequest;
import com.googlesource.gerrit.plugins.its.base.workflow.Property;
import com.googlesource.gerrit.plugins.its.base.workflow.action.AddVelocityComment.VelocityAdapterItsFacade;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.runtime.RuntimeInstance;
import org.easymock.Capture;
import org.easymock.EasyMock;
import org.easymock.IAnswer;
import org.eclipse.jgit.util.FileUtils;

public class AddVelocityCommentTest extends LoggingMockingTestCase {
  private Injector injector;

  private Path sitePath;
  private ItsFacade its;
  private RuntimeInstance velocityRuntime;

  private boolean cleanupSitePath;

  public void testWarnNoTemplateNameGiven() throws IOException {
    ActionRequest actionRequest = createMock(ActionRequest.class);
    expect(actionRequest.getParameter(1)).andReturn("");
    replayMocks();

    AddVelocityComment addVelocityComment = createAddVelocityComment();
    addVelocityComment.execute("4711", actionRequest, new HashSet<>());

    assertLogMessageContains("No template name");
  }

  public void testInlinePlain() throws IOException {
    ActionRequest actionRequest = createMock(ActionRequest.class);
    expect(actionRequest.getParameter(1)).andReturn("inline");
    expect(actionRequest.getParameters()).andReturn(new String[] {"inline", "Simple-text"});

    IAnswer<Boolean> answer = new VelocityWriterFiller("Simple-text");
    expect(
            velocityRuntime.evaluate(
                (VelocityContext) anyObject(),
                (Writer) anyObject(),
                (String) anyObject(),
                eq("Simple-text")))
        .andAnswer(answer);

    its.addComment("4711", "Simple-text");

    replayMocks();

    AddVelocityComment addVelocityComment = createAddVelocityComment();
    addVelocityComment.execute("4711", actionRequest, new HashSet<>());
  }

  public void testInlineWithMultipleParameters() throws IOException {
    ActionRequest actionRequest = createMock(ActionRequest.class);
    expect(actionRequest.getParameter(1)).andReturn("inline");
    expect(actionRequest.getParameters()).andReturn(new String[] {"inline", "Param2", "Param3"});

    Set<Property> properties = Sets.newHashSet();

    IAnswer<Boolean> answer = new VelocityWriterFiller("Param2 Param3");
    expect(
            velocityRuntime.evaluate(
                (VelocityContext) anyObject(),
                (Writer) anyObject(),
                (String) anyObject(),
                eq("Param2 Param3")))
        .andAnswer(answer);

    its.addComment("4711", "Param2 Param3");

    replayMocks();

    AddVelocityComment addVelocityComment = createAddVelocityComment();
    addVelocityComment.execute("4711", actionRequest, properties);
  }

  public void testInlineWithSingleProperty() throws IOException {
    ActionRequest actionRequest = createMock(ActionRequest.class);
    expect(actionRequest.getParameter(1)).andReturn("inline");
    expect(actionRequest.getParameters()).andReturn(new String[] {"inline", "${subject}"});

    Set<Property> properties = Sets.newHashSet();

    Property propertySubject = createMock(Property.class);
    expect(propertySubject.getKey()).andReturn("subject").anyTimes();
    expect(propertySubject.getValue()).andReturn("Rosebud").anyTimes();
    properties.add(propertySubject);

    IAnswer<Boolean> answer = new VelocityWriterFiller("Rosebud");
    Capture<VelocityContext> contextCapture = createCapture();
    expect(
            velocityRuntime.evaluate(
                capture(contextCapture),
                (Writer) anyObject(),
                (String) anyObject(),
                eq("${subject}")))
        .andAnswer(answer);

    its.addComment("4711", "Rosebud");

    replayMocks();

    AddVelocityComment addVelocityComment = createAddVelocityComment();
    addVelocityComment.execute("4711", actionRequest, properties);

    VelocityContext context = contextCapture.getValue();
    assertEquals("Subject property of context did not match", "Rosebud", context.get("subject"));
  }

  public void testInlineWithUnusedProperty() throws IOException {
    ActionRequest actionRequest = createMock(ActionRequest.class);
    expect(actionRequest.getParameter(1)).andReturn("inline");
    expect(actionRequest.getParameters()).andReturn(new String[] {"inline", "Test"});

    Set<Property> properties = Sets.newHashSet();

    Property propertySubject = createMock(Property.class);
    expect(propertySubject.getKey()).andReturn("subject").anyTimes();
    expect(propertySubject.getValue()).andReturn("Rosebud").anyTimes();
    properties.add(propertySubject);

    IAnswer<Boolean> answer = new VelocityWriterFiller("Test");
    expect(
            velocityRuntime.evaluate(
                (VelocityContext) anyObject(),
                (Writer) anyObject(),
                (String) anyObject(),
                eq("Test")))
        .andAnswer(answer);

    its.addComment("4711", "Test");

    replayMocks();

    AddVelocityComment addVelocityComment = createAddVelocityComment();
    addVelocityComment.execute("4711", actionRequest, properties);
  }

  public void testInlineWithMultipleProperties() throws IOException {
    ActionRequest actionRequest = createMock(ActionRequest.class);
    expect(actionRequest.getParameter(1)).andReturn("inline");
    expect(actionRequest.getParameters())
        .andReturn(new String[] {"inline", "${subject}", "${reason}", "${subject}"});

    Set<Property> properties = Sets.newHashSet();

    Property propertySubject = createMock(Property.class);
    expect(propertySubject.getKey()).andReturn("subject").anyTimes();
    expect(propertySubject.getValue()).andReturn("Rosebud").anyTimes();
    properties.add(propertySubject);

    Property propertyReason = createMock(Property.class);
    expect(propertyReason.getKey()).andReturn("reason").anyTimes();
    expect(propertyReason.getValue()).andReturn("Life").anyTimes();
    properties.add(propertyReason);

    IAnswer<Boolean> answer = new VelocityWriterFiller("Rosebud Life Rosebud");
    Capture<VelocityContext> contextCapture = createCapture();
    expect(
            velocityRuntime.evaluate(
                capture(contextCapture),
                (Writer) anyObject(),
                (String) anyObject(),
                eq("${subject} ${reason} ${subject}")))
        .andAnswer(answer);

    its.addComment("4711", "Rosebud Life Rosebud");

    replayMocks();

    AddVelocityComment addVelocityComment = createAddVelocityComment();
    addVelocityComment.execute("4711", actionRequest, properties);

    VelocityContext context = contextCapture.getValue();
    assertEquals("Subject property of context did not match", "Rosebud", context.get("subject"));
    assertEquals("Reason property of context did not match", "Life", context.get("reason"));
  }

  public void testItsWrapperFormatLink1Parameter()
      throws IOException, SecurityException, IllegalArgumentException {
    ActionRequest actionRequest = createMock(ActionRequest.class);
    expect(actionRequest.getParameter(1)).andReturn("inline");
    expect(actionRequest.getParameters()).andReturn(new String[] {"inline", "Simple-Text"});

    IAnswer<Boolean> answer = new VelocityWriterFiller("Simple-Text");
    Capture<VelocityContext> contextCapture = createCapture();
    expect(
            velocityRuntime.evaluate(
                capture(contextCapture),
                (Writer) anyObject(),
                (String) anyObject(),
                eq("Simple-Text")))
        .andAnswer(answer);

    its.addComment("4711", "Simple-Text");

    expect(its.createLinkForWebui("http://www.example.org/", "http://www.example.org/"))
        .andReturn("Formatted Link");

    replayMocks();

    AddVelocityComment addVelocityComment = createAddVelocityComment();
    addVelocityComment.execute("4711", actionRequest, new HashSet<>());

    VelocityContext context = contextCapture.getValue();
    Object itsAdapterObj = context.get("its");
    assertNotNull("its property is null", itsAdapterObj);
    assertTrue(
        "Its is not a VelocityAdapterItsFacade instance",
        itsAdapterObj instanceof VelocityAdapterItsFacade);
    VelocityAdapterItsFacade itsAdapter = (VelocityAdapterItsFacade) itsAdapterObj;
    String formattedLink = itsAdapter.formatLink("http://www.example.org/");
    assertEquals("Result of formatLink does not match", "Formatted Link", formattedLink);
  }

  public void testItsWrapperFormatLink2Parameters()
      throws IOException, SecurityException, IllegalArgumentException {
    ActionRequest actionRequest = createMock(ActionRequest.class);
    expect(actionRequest.getParameter(1)).andReturn("inline");
    expect(actionRequest.getParameters()).andReturn(new String[] {"inline", "Simple-Text"});

    IAnswer<Boolean> answer = new VelocityWriterFiller("Simple-Text");
    Capture<VelocityContext> contextCapture = createCapture();
    expect(
            velocityRuntime.evaluate(
                capture(contextCapture),
                (Writer) anyObject(),
                (String) anyObject(),
                eq("Simple-Text")))
        .andAnswer(answer);

    its.addComment("4711", "Simple-Text");

    expect(its.createLinkForWebui("http://www.example.org/", "Caption"))
        .andReturn("Formatted Link");

    replayMocks();

    AddVelocityComment addVelocityComment = createAddVelocityComment();
    addVelocityComment.execute("4711", actionRequest, new HashSet<>());

    VelocityContext context = contextCapture.getValue();
    Object itsAdapterObj = context.get("its");
    assertNotNull("its property is null", itsAdapterObj);
    assertTrue(
        "Its is not a VelocityAdapterItsFacade instance",
        itsAdapterObj instanceof VelocityAdapterItsFacade);
    VelocityAdapterItsFacade itsAdapter = (VelocityAdapterItsFacade) itsAdapterObj;
    String formattedLink = itsAdapter.formatLink("http://www.example.org/", "Caption");
    assertEquals("Result of formatLink does not match", "Formatted Link", formattedLink);
  }

  public void testWarnTemplateNotFound() throws IOException {
    ActionRequest actionRequest = createMock(ActionRequest.class);
    expect(actionRequest.getParameter(1)).andReturn("non-existing-template");

    replayMocks();

    AddVelocityComment addVelocityComment = createAddVelocityComment();
    addVelocityComment.execute("4711", actionRequest, new HashSet<>());

    assertLogMessageContains("non-existing-template");
  }

  public void testTemplateSimple() throws IOException {
    ActionRequest actionRequest = createMock(ActionRequest.class);
    expect(actionRequest.getParameter(1)).andReturn("test-template");

    injectTestTemplate("Simple Test Template");

    IAnswer<Boolean> answer = new VelocityWriterFiller("Simple Test Template");
    expect(
            velocityRuntime.evaluate(
                (VelocityContext) anyObject(),
                (Writer) anyObject(),
                (String) anyObject(),
                eq("Simple Test Template")))
        .andAnswer(answer);

    its.addComment("4711", "Simple Test Template");

    replayMocks();

    AddVelocityComment addVelocityComment = createAddVelocityComment();
    addVelocityComment.execute("4711", actionRequest, new HashSet<>());
  }

  public void testTemplateMultipleParametersAndProperties() throws IOException {
    ActionRequest actionRequest = createMock(ActionRequest.class);
    expect(actionRequest.getParameter(1)).andReturn("test-template");

    Set<Property> properties = Sets.newHashSet();

    Property propertySubject = createMock(Property.class);
    expect(propertySubject.getKey()).andReturn("subject").anyTimes();
    expect(propertySubject.getValue()).andReturn("Rosebud").anyTimes();
    properties.add(propertySubject);

    Property propertyReason = createMock(Property.class);
    expect(propertyReason.getKey()).andReturn("reason").anyTimes();
    expect(propertyReason.getValue()).andReturn("Life").anyTimes();
    properties.add(propertyReason);

    injectTestTemplate(
        "Test Template with subject: ${subject}.\n" + "${reason} is the reason for ${subject}.");

    IAnswer<Boolean> answer =
        new VelocityWriterFiller(
            "Test Template with subject: Rosebud.\n" + "Life is the reason for Rosebud.");
    Capture<VelocityContext> contextCapture = createCapture();
    expect(
            velocityRuntime.evaluate(
                capture(contextCapture),
                (Writer) anyObject(),
                (String) anyObject(),
                eq(
                    "Test Template with subject: ${subject}.\n"
                        + "${reason} is the reason for ${subject}.")))
        .andAnswer(answer);

    its.addComment(
        "4711", "Test Template with subject: Rosebud.\n" + "Life is the reason for Rosebud.");

    replayMocks();

    AddVelocityComment addVelocityComment = createAddVelocityComment();
    addVelocityComment.execute("4711", actionRequest, properties);

    VelocityContext context = contextCapture.getValue();
    assertEquals("Subject property of context did not match", "Rosebud", context.get("subject"));
    assertEquals("Reason property of context did not match", "Life", context.get("reason"));
  }

  private AddVelocityComment createAddVelocityComment() {
    return injector.getInstance(AddVelocityComment.class);
  }

  private void injectTestTemplate(String template) throws IOException {
    File templateParentFile =
        new File(
            sitePath.toFile(), "etc" + File.separatorChar + "its" + File.separator + "templates");
    assertTrue(
        "Failed to create parent (" + templateParentFile + ") for " + "rule base",
        templateParentFile.mkdirs());
    File templateFile = new File(templateParentFile, "test-template.vm");

    try (FileWriter unbufferedWriter = new FileWriter(templateFile);
        BufferedWriter writer = new BufferedWriter(unbufferedWriter)) {
      writer.write(template);
    }
  }

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

  @Override
  public void tearDown() throws Exception {
    if (cleanupSitePath) {
      if (Files.exists(sitePath)) {
        FileUtils.delete(sitePath.toFile(), FileUtils.RECURSIVE);
      }
    }
    super.tearDown();
  }

  private Path randomTargetPath() {
    return Paths.get("target", "random-name-" + UUID.randomUUID().toString());
  }

  private class TestModule extends FactoryModule {
    @Override
    protected void configure() {
      sitePath = randomTargetPath();
      assertFalse("sitePath already (" + sitePath + ") already exists", Files.exists(sitePath));
      cleanupSitePath = true;

      bind(Path.class).annotatedWith(SitePath.class).toInstance(sitePath);

      its = createMock(ItsFacade.class);
      bind(ItsFacade.class).toInstance(its);

      velocityRuntime = createMock(RuntimeInstance.class);
      bind(RuntimeInstance.class).toInstance(velocityRuntime);
    }
  }

  private class VelocityWriterFiller implements IAnswer<Boolean> {
    private final String fill;
    private final boolean returnValue;

    private VelocityWriterFiller(String fill, boolean returnValue) {
      this.fill = fill;
      this.returnValue = returnValue;
    }

    private VelocityWriterFiller(String fill) {
      this(fill, true);
    }

    @Override
    public Boolean answer() throws Throwable {
      Object[] arguments = EasyMock.getCurrentArguments();
      Writer writer = (Writer) arguments[1];
      writer.write(fill);
      return returnValue;
    }
  }
}
