/*
 * 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.drill.test;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;

import org.apache.commons.io.FileUtils;
import org.apache.drill.shaded.guava.com.google.common.base.Charsets;
import org.junit.runner.Description;

/**
 * <h4>Overview</h4>
 * <p>
 * This is a {@link DirTestWatcher} which creates all the temporary directories required by a Drillbit and the various <b>dfs.*</b> storage workspaces. It also
 * provides convenience methods that do the following:
 *
 * <ol>
 *   <li>Copy project files to temp directories. This is useful for copying the sample data into a temp directory.</li>
 *   <li>Copy resource files to temp.</li>
 *   <li>Updating parquet metadata files.</li>
 * </ol>
 * </p>
 *
 * <p>
 *   The {@link BaseDirTestWatcher} creates the following directories in the <b>base temp directory</b> (for a description of where the <b>base temp directory</b>
 *   is located please read the docs for {@link DirTestWatcher}):
 *
 *   <ul>
 *     <li><b>tmp:</b> {@link #getTmpDir()}</li>
 *     <li><b>store:</b> {@link #getStoreDir()}</li>
 *     <li><b>root:</b> {@link #getRootDir()}</li>
 *     <li><b>dfsTestTmp:</b> {@link #getDfsTestTmpDir()}</li>
 *   </ul>
 * </p>
 *
 * <h4>Examples</h4>
 * <p>
 *   The {@link BaseDirTestWatcher} is used in {@link BaseTestQuery} and an example of how it is used in conjunction with the {@link ClusterFixture} can be found in
 *   {@link ExampleTest}.
 * </p>
 */
public class BaseDirTestWatcher extends DirTestWatcher {
  /**
   * An enum used to represent the directories mapped to the <b>dfs.root</b> and <b>dfs.tmp</b> workspaces repectively.
   */
  public enum DirType {
    ROOT, // Corresponds to the directory that should be mapped to dfs.root
    TEST_TMP // Corresponds to the directory that should be mapped to dfs.tmp
  }

  private File codegenDir;
  private File spillDir;
  private File tmpDir;
  private File storeDir;
  private File dfsTestTmpParentDir;
  private File dfsTestTmpDir;
  private File rootDir;

  /**
   * Creates a {@link BaseDirTestWatcher} which does not delete it's temp directories at the end of tests.
   */
  public BaseDirTestWatcher() {
    super();
  }

  /**
   * Creates a {@link BaseDirTestWatcher}.
   * @param deleteDirAtEnd If true, temp directories are deleted at the end of tests. If false, temp directories are not deleted at the end of tests.
   */
  public BaseDirTestWatcher(boolean deleteDirAtEnd) {
    super(deleteDirAtEnd);
  }

  public void start(Class<?> suite) {
    starting(Description.createSuiteDescription(suite));
  }

  @Override
  protected void starting(Description description) {
    super.starting(description);

    codegenDir = makeSubDir(Paths.get("codegen"));
    spillDir = makeSubDir(Paths.get("spill"));
    rootDir = makeSubDir(Paths.get("root"));
    tmpDir = makeSubDir(Paths.get("tmp"));
    storeDir = makeSubDir(Paths.get("store"));
    dfsTestTmpParentDir = makeSubDir(Paths.get("dfsTestTmp"));

    newDfsTestTmpDir();
  }

  /**
   * Clear contents of cluster directories
   */
  public void clear() {
    try {
      FileUtils.cleanDirectory(codegenDir);
      FileUtils.cleanDirectory(spillDir);
      FileUtils.cleanDirectory(rootDir);
      FileUtils.cleanDirectory(tmpDir);
      FileUtils.cleanDirectory(storeDir);
      FileUtils.cleanDirectory(dfsTestTmpDir);
    } catch (IOException e) {
      throw new RuntimeException(e);
    }
  }

  /**
   * Gets the temp directory that should be used as a Drillbit's tmp directory.
   * @return The temp directory that should be used as a Drillbit's tmp directory.
   */
  public File getTmpDir() {
    return tmpDir;
  }

  /**
   * Gets the temp directory that should be used by the {@link org.apache.drill.exec.store.sys.store.LocalPersistentStore}.
   * @return The temp directory that should be used by the {@link org.apache.drill.exec.store.sys.store.LocalPersistentStore}.
   */
  public File getStoreDir() {
    return storeDir;
  }

  /**
   * Gets the temp directory that should be used by the <b>dfs.tmp</b> workspace.
   * @return The temp directory that should be used by the <b>dfs.tmp</b> workspace.
   */
  public File getDfsTestTmpDir() {
    return dfsTestTmpDir;
  }

  /**
   * Gets the temp directory that should be used to hold the contents of the <b>dfs.root</b> workspace.
   * @return The temp directory that should be used to hold the contents of the <b>dfs.root</b> workspace.
   */
  public File getRootDir() {
    return rootDir;
  }

  /**
   * Gets the temp directory that should be used to save generated code files.
   * @return The temp directory that should be used to save generated code files.
   */
  public File getCodegenDir() {
    return codegenDir;
  }

  public File getSpillDir() {
    return spillDir;
  }

  /**
   * This methods creates a new directory which can be mapped to <b>dfs.tmp</b>.
   */
  public void newDfsTestTmpDir() {
    dfsTestTmpDir = DirTestWatcher.createTempDir(dfsTestTmpParentDir);
  }

  /**
   * A helper method which returns the correct directory corresponding to the given {@link DirType}.
   * @param type The directory to return.
   * @return The directory corresponding to the given {@link DirType}.
   */
  private File getDir(DirType type) {
    switch (type) {
      case ROOT:
        return rootDir;
      case TEST_TMP:
        return dfsTestTmpDir;
      default:
        throw new IllegalArgumentException(String.format("Unsupported type %s", type));
    }
  }

  /**
   * Creates a directory in the temp root directory (corresponding to <b>dfs.root</b>) at the given relative path.
   * @param relPath The relative path in the temp root directory at which to create a directory.
   * @return The {@link java.io.File} corresponding to the sub directory that was created.
   */
  public File makeRootSubDir(Path relPath) {
    return makeSubDir(relPath, DirType.ROOT);
  }

  /**
   * Creates a directory in the temp tmp directory (corresponding to <b>dfs.tmp</b>) at the given relative path.
   * @param relPath The relative path in the temp tmp directory at which to create a directory.
   * @return The {@link java.io.File} corresponding to the sub directory that was created.
   */
  public File makeTestTmpSubDir(Path relPath) {
    return makeSubDir(relPath, DirType.TEST_TMP);
  }

  private File makeSubDir(Path relPath, DirType type) {
    File subDir = getDir(type)
      .toPath()
      .resolve(relPath)
      .toFile();
    subDir.mkdirs();
    return subDir;
  }

  /**
   * This copies a file or directory from <b>src/test/resources</b> into the temp root directory (corresponding to <b>dfs.root</b>). The relative path of the file or
   * directory in <b>src/test/resources</b> is preserved in the temp root directory.
   * @param relPath The relative path of the file or directory in <b>src/test/resources</b> to copy into the root temp folder.
   * @return The {@link java.io.File} corresponding to the copied file or directory in the temp root directory.
   */
  public File copyResourceToRoot(Path relPath) {
    return copyTo(relPath, relPath, TestTools.FileSource.RESOURCE, DirType.ROOT);
  }

  /**
   * This copies a filed or directory from the maven project into the temp root directory (corresponding to <b>dfs.root</b>). The relative path of the file or directory
   * in the maven module is preserved in the temp root directory.
   * @param relPath The relative path of the file or directory in the maven module to copy into the root temp folder.
   * @return The {@link java.io.File} corresponding to the copied file or directory in the temp root directory.
   */
  public File copyFileToRoot(Path relPath) {
    return copyTo(relPath, relPath, TestTools.FileSource.PROJECT, DirType.ROOT);
  }

  /**
   * This copies a file or directory from <b>src/test/resources</b> into the temp root directory (corresponding to <b>dfs.root</b>). The file or directory is copied
   * to the provided relative destPath in the temp root directory.
   * @param relPath The source relative path of a file or directory from <b>src/test/resources</b> that will be copied.
   * @param destPath The destination relative path of the file or directory in the temp root directory.
   * @return The {@link java.io.File} corresponding to the final copied file or directory in the temp root directory.
   */
  public File copyResourceToRoot(Path relPath, Path destPath) {
    return copyTo(relPath, destPath, TestTools.FileSource.RESOURCE, DirType.ROOT);
  }

  /**
   * Removes a file or directory copied at relativePath inside the root directory
   * @param relPath - relative path of file/directory to be deleted from the root directory
   * @throws IOException - Throws exception in case of failure
   */
  public void removeFileFromRoot(Path relPath) throws IOException {
    removeFromRoot(relPath, DirType.ROOT);
  }

  private void removeFromRoot(Path relPath, DirType dirType) throws IOException {
    final File baseDir = getDir(dirType);
    final Path finalPath = baseDir.toPath().resolve(relPath);
    final File file = finalPath.toFile();
    FileUtils.forceDelete(file);
  }

  /**
   * This copies a file or directory from <b>src/test/resources</b> into the temp root directory (corresponding to <b>dfs.root</b>). The file or directory is copied
   * to the provided relative destPath in the temp root directory.
   * @param relPath The source relative path of a file or directory from <b>src/test/resources</b> that will be copied.
   * @param destPath The destination relative path of the file or directory in the temp root directory.
   * @return The {@link java.io.File} corresponding to the final copied file or directory in the temp root directory.
   */
  public File copyResourceToTestTmp(Path relPath, Path destPath) {
    return copyTo(relPath, destPath, TestTools.FileSource.RESOURCE, DirType.TEST_TMP);
  }

  private File copyTo(Path relPath, Path destPath, TestTools.FileSource fileSource, DirType dirType) {
    File file = TestTools.getFile(relPath, fileSource);

    if (file.isDirectory()) {
      File subDir = makeSubDir(destPath, dirType);
      TestTools.copyDirToDest(relPath, subDir, fileSource);
      return subDir;
    } else {
      File baseDir = getDir(dirType);

      baseDir.toPath()
        .resolve(destPath)
        .getParent()
        .toFile()
        .mkdirs();

      File destFile = baseDir.toPath()
        .resolve(destPath)
        .toFile();

      try {
        destFile.createNewFile();
        FileUtils.copyFile(file, destFile);
      } catch (IOException e) {
        throw new RuntimeException("This should not happen", e);
      }

      return destFile;
    }
  }

  /**
   * This is a convenience method that replaces placeholders in test parquet metadata files.
   * @param metaDataFile The parquet metadata file to do string replacement on.
   * @param replacePath The path to replace <b>REPLACED_IN_TEST</b> with in the parquet metadata file.
   * @param customStringReplacement If this is provided a <b>CUSTOM_STRING_REPLACEMENT</b> is replaced in the parquet metadata file with this string.
   */
  public void replaceMetaDataContents(File metaDataFile, File replacePath, String customStringReplacement) {
    try {
      String metadataFileContents = FileUtils.readFileToString(metaDataFile, Charsets.UTF_8);

      if (customStringReplacement != null) {
        metadataFileContents = metadataFileContents.replace("CUSTOM_STRING_REPLACEMENT", customStringReplacement);
      }

      metadataFileContents = metadataFileContents.replace("REPLACED_IN_TEST", replacePath.getCanonicalPath());
      FileUtils.write(metaDataFile, metadataFileContents, Charsets.UTF_8);
    } catch (IOException e) {
      throw new RuntimeException("This should not happen", e);
    }
  }
}
