/*
 * 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.geode.management.internal.cli.shell;

import static java.lang.System.lineSeparator;
import static java.nio.charset.Charset.defaultCharset;
import static java.nio.file.Files.createDirectory;
import static java.nio.file.Files.createFile;
import static org.apache.commons.io.FileUtils.writeStringToFile;
import static org.apache.geode.management.internal.cli.shell.GfshConfig.DEFAULT_INIT_FILE_NAME;
import static org.assertj.core.api.Assertions.assertThat;

import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.lang.reflect.Field;
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.logging.Handler;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.stream.Collectors;

import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;
import org.junit.contrib.java.lang.system.RestoreSystemProperties;
import org.junit.rules.TemporaryFolder;

import org.apache.geode.management.internal.cli.LogWrapper;

/**
 * Unit tests for supplying an init file to Gfsh.
 *
 * <p>
 * Makes use of reflection to reset private static variables on some classes to replace loggers that
 * would otherwise clutter the console.
 */
@Ignore("Rewrite GfshInitFileIntegrationTest without using reflection to change Gfsh statics")
public class GfshInitFileIntegrationTest {

  private static final int BANNER_LINE_COUNT = 1;
  private static final int INIT_FILE_CITATION_LINE_COUNT = 1;

  private static Logger logger;
  private static Handler[] savedHandlers;

  private CollectingHandler collectingHandler;

  private Path gfshHistoryFilePath;
  private Path gfshLogDirPath;
  private Path initFilePath;

  @Rule
  public TemporaryFolder temporaryFolder = new TemporaryFolder();

  @Rule
  public RestoreSystemProperties restoreSystemProperties = new RestoreSystemProperties();

  /**
   * Turn off console logging from JUL for the duration of this class's tests, to reduce
   * noise level of output in automated build.
   */
  @BeforeClass
  public static void setUpBeforeClass() {
    logger = Logger.getLogger("");
    savedHandlers = logger.getHandlers();
    for (Handler handler : savedHandlers) {
      logger.removeHandler(handler);
    }
  }

  /**
   * Restore logging to state prior to the execution of this class
   */
  @AfterClass
  public static void tearDownAfterClass() {
    for (Handler handler : savedHandlers) {
      logger.addHandler(handler);
    }

    Gfsh.getCurrentInstance().stop();
  }

  @Before
  public void setUp() throws Exception {
    gfshHistoryFilePath = temporaryFolder.getRoot().toPath().resolve("history").toAbsolutePath();
    gfshLogDirPath = temporaryFolder.getRoot().toPath().resolve("logs").toAbsolutePath();
    initFilePath =
        temporaryFolder.getRoot().toPath().resolve(DEFAULT_INIT_FILE_NAME).toAbsolutePath();

    createFile(gfshHistoryFilePath);
    createDirectory(gfshLogDirPath);

    collectingHandler = new CollectingHandler();
    initializeGfshStatics(logger, collectingHandler);

    Gfsh.gfshout = new PrintStream(new ByteArrayOutputStream());
  }

  @After
  public void tearDown() {
    logger.removeHandler(collectingHandler);
  }

  @Test
  public void initFile_isNull() {
    GfshConfig gfshConfig = new GfshConfig(gfshHistoryFilePath.toString(), "", 0,
        gfshLogDirPath.toString(), null, null, null, null);
    Gfsh gfsh = Gfsh.getInstance(false, null, gfshConfig);

    assertThat(gfsh.getLastExecutionStatus())
        .as("gfsh last execution status (success is zero)")
        .isZero();

    assertThat(collectingHandler.getLogMessages())
        .as("log messages")
        .hasSize(BANNER_LINE_COUNT);

    assertThat(collectingHandler.getLogThrowables())
        .as("log throwables")
        .isEmpty();
  }

  @Test
  public void initFile_doesNotExist() {
    GfshConfig gfshConfig = new GfshConfig(gfshHistoryFilePath.toString(), "", 0,
        gfshLogDirPath.toString(), null, null, null, initFilePath.toString());
    Gfsh gfsh = Gfsh.getInstance(false, null, gfshConfig);

    assertThat(gfsh.getLastExecutionStatus())
        .as("gfsh last execution status (failure is non-zero)")
        .isNotZero();

    assertThat(collectingHandler.getLogMessages())
        .as("log messages")
        .hasSize(BANNER_LINE_COUNT + INIT_FILE_CITATION_LINE_COUNT + 1);

    assertThat(collectingHandler.getLogThrowables())
        .as("log throwables")
        .isNotEmpty();
  }

  @Test
  public void initFile_existsButIsEmpty() throws Exception {
    createFile(initFilePath);
    GfshConfig gfshConfig = new GfshConfig(gfshHistoryFilePath.toString(), "", 0,
        gfshLogDirPath.toString(), null, null, null, initFilePath.toString());
    Gfsh gfsh = Gfsh.getInstance(false, null, gfshConfig);

    assertThat(gfsh.getLastExecutionStatus())
        .as("gfsh last execution status (success is zero)")
        .isZero();

    assertThat(collectingHandler.getLogMessages())
        .as("log messages")
        .hasSize(BANNER_LINE_COUNT + INIT_FILE_CITATION_LINE_COUNT + 1);

    assertThat(collectingHandler.getLogThrowables())
        .as("log throwables")
        .isEmpty();
  }

  @Test
  public void initFile_existsAndContains_oneGoodCommand() throws Exception {
    writeStringToFile(initFilePath.toFile(), "echo --string=hello" + lineSeparator(),
        defaultCharset());
    GfshConfig gfshConfig = new GfshConfig(gfshHistoryFilePath.toString(), "", 0,
        gfshLogDirPath.toString(), null, null, null, initFilePath.toString());
    Gfsh gfsh = Gfsh.getInstance(false, null, gfshConfig);

    assertThat(gfsh.getLastExecutionStatus())
        .as("gfsh last execution status (success is zero)")
        .isZero();

    assertThat(collectingHandler.getLogMessages())
        .as("log messages")
        .hasSize(BANNER_LINE_COUNT + INIT_FILE_CITATION_LINE_COUNT + 1);

    assertThat(collectingHandler.getLogThrowables())
        .as("log throwables")
        .isEmpty();
  }

  @Test
  public void initFile_existsAndContains_twoGoodCommands() throws Exception {
    writeStringToFile(initFilePath.toFile(), "echo --string=hello" + lineSeparator(),
        defaultCharset());
    writeStringToFile(initFilePath.toFile(), "echo --string=goodbye" + lineSeparator(),
        defaultCharset(), true);
    GfshConfig gfshConfig = new GfshConfig(gfshHistoryFilePath.toString(), "", 0,
        gfshLogDirPath.toString(), null, null, null, initFilePath.toString());
    Gfsh gfsh = Gfsh.getInstance(false, null, gfshConfig);

    assertThat(gfsh.getLastExecutionStatus())
        .as("gfsh last execution status (success is zero)")
        .isZero();

    assertThat(collectingHandler.getLogMessages())
        .as("log messages")
        .hasSize(BANNER_LINE_COUNT + INIT_FILE_CITATION_LINE_COUNT + 1);

    assertThat(collectingHandler.getLogThrowables())
        .as("log throwables")
        .isEmpty();
  }

  @Test
  public void initFile_existsAndContains_oneBadCommand() throws Exception {
    writeStringToFile(initFilePath.toFile(), "fail" + lineSeparator(), defaultCharset());
    GfshConfig gfshConfig = new GfshConfig(gfshHistoryFilePath.toString(), "", 0,
        gfshLogDirPath.toString(), null, null, null, initFilePath.toString());
    Gfsh gfsh = Gfsh.getInstance(false, null, gfshConfig);

    assertThat(gfsh.getLastExecutionStatus())
        .as("gfsh last execution status (failure is non-zero)")
        .isNotZero();

    // after upgrading to Spring-shell 1.2, the bad command exception is logged as well
    assertThat(collectingHandler.getLogMessages())
        .as("log messages")
        .hasSize(BANNER_LINE_COUNT + INIT_FILE_CITATION_LINE_COUNT + 2);
  }

  @Test
  public void initFile_existsAndContains_twoBadCommands() throws Exception {
    writeStringToFile(initFilePath.toFile(), "fail" + lineSeparator(), defaultCharset());
    writeStringToFile(initFilePath.toFile(), "fail" + lineSeparator(), defaultCharset(), true);
    GfshConfig gfshConfig = new GfshConfig(gfshHistoryFilePath.toString(), "", 0,
        gfshLogDirPath.toString(), null, null, null, initFilePath.toString());
    Gfsh gfsh = Gfsh.getInstance(false, null, gfshConfig);

    assertThat(gfsh.getLastExecutionStatus())
        .as("gfsh last execution status (failure is non-zero)")
        .isNotZero();

    // after upgrading to Spring-shell 1.2, the bad command exception is logged as well
    assertThat(collectingHandler.getLogMessages())
        .as("log messages")
        .hasSize(BANNER_LINE_COUNT + INIT_FILE_CITATION_LINE_COUNT + 2);
  }

  @Test
  public void initFile_existsAndContains_badAndGoodCommands() throws Exception {
    writeStringToFile(initFilePath.toFile(), "fail" + lineSeparator(), defaultCharset());
    writeStringToFile(initFilePath.toFile(), "echo --string=goodbye" + lineSeparator(),
        defaultCharset(), true);
    GfshConfig gfshConfig = new GfshConfig(gfshHistoryFilePath.toString(), "", 0,
        gfshLogDirPath.toString(), null, null, null, initFilePath.toString());
    Gfsh gfsh = Gfsh.getInstance(false, null, gfshConfig);

    assertThat(gfsh.getLastExecutionStatus())
        .as("gfsh last execution status (failure is non-zero)")
        .isNotZero();

    // after upgrading to Spring-shell 1.2, the bad command exception is logged as well
    assertThat(collectingHandler.getLogMessages())
        .as("log messages")
        .hasSize(BANNER_LINE_COUNT + INIT_FILE_CITATION_LINE_COUNT + 2);
  }

  private static void initializeGfshStatics(Logger logger, Handler handler)
      throws NoSuchFieldException, IllegalAccessException {
    // Null out static instance so can reinitialise
    Field gfsh_instance = Gfsh.class.getDeclaredField("instance");
    gfsh_instance.setAccessible(true);
    gfsh_instance.set(null, null);

    LogWrapper gfshFileLogger = LogWrapper.getInstance(null);
    Field logWrapper_INSTANCE = LogWrapper.class.getDeclaredField("INSTANCE");
    logWrapper_INSTANCE.setAccessible(true);
    logWrapper_INSTANCE.set(null, gfshFileLogger);

    Field logWrapper_logger = LogWrapper.class.getDeclaredField("logger");
    logWrapper_logger.setAccessible(true);
    logger.addHandler(handler);
    logWrapper_logger.set(gfshFileLogger, logger);
  }

  /**
   * Log handler for testing. Capture logged messages for later inspection.
   *
   * @see Handler#publish(LogRecord)
   */
  private static class CollectingHandler extends Handler {

    private final List<LogRecord> log;

    CollectingHandler() {
      log = new CopyOnWriteArrayList<>();
    }

    Collection<String> getLogMessages() {
      return log.stream()
          .map(LogRecord::getMessage)
          .collect(Collectors.toList());
    }

    Collection<Throwable> getLogThrowables() {
      return log.stream()
          .map(LogRecord::getThrown)
          .filter(Objects::nonNull)
          .collect(Collectors.toList());
    }

    @Override
    public void publish(LogRecord record) {
      log.add(record);
    }

    @Override
    public void flush() {
      // nothing
    }

    @Override
    public void close() throws SecurityException {
      // nothing
    }
  }
}
