/*
 * Copyright (C) 2014 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.android.jack.test.helper;

import com.android.jack.backend.jayce.JayceFileImporter;
import com.android.jack.library.FileType;
import com.android.jack.library.InputJackLibrary;
import com.android.jack.library.LibraryIOException;
import com.android.jack.test.runner.AbstractRuntimeRunner;
import com.android.jack.test.runner.RuntimeRunner;
import com.android.jack.test.toolchain.AbstractTestTools;
import com.android.jack.test.toolchain.IToolchain;
import com.android.jack.test.toolchain.IncrementalToolchain;
import com.android.jack.test.toolchain.JackBasedToolchain;
import com.android.jack.test.toolchain.JackBasedToolchain.MultiDexKind;
import com.android.jack.test.toolchain.JackCliToolchain;
import com.android.jack.test.toolchain.JillBasedToolchain;
import com.android.jack.test.toolchain.LegacyJillToolchain;
import com.android.jack.test.toolchain.TwoStepsToolchain;
import com.android.sched.vfs.InputVFile;
import com.android.sched.vfs.VPath;

import junit.framework.Assert;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;

/**
 * This class is used to write tests on incremental compilation.
 */
public class IncrementalTestHelper {

  @Nonnull
  private final File testingFolder;
  @Nonnull
  private final File sourceFolder;
  @Nonnull
  private final File dexOutDir;
  @Nonnull
  private final File dexFile;
  @Nonnull
  private final File compilerStateFolder;
  @Nonnull
  private final Set<File> javaFiles = new HashSet<File>();
  @Nonnull
  private final Map<VPath, Long> fileModificationDate = new HashMap<VPath, Long>();
  @Nonnull
  private OutputStream out = System.out;
  @Nonnull
  private OutputStream err = System.err;

  private boolean isApiTest = false;

  public IncrementalTestHelper(@Nonnull File testingFolder) throws IOException {
    this.testingFolder = testingFolder;
    this.sourceFolder = new File(testingFolder, "src");
    if (!this.sourceFolder.mkdirs()) {
      throw new IOException("Failed to create folder " + this.sourceFolder.getAbsolutePath());
    }
    compilerStateFolder = new File(testingFolder, "compileState");
    if (!compilerStateFolder.exists() && !compilerStateFolder.mkdir()) {
      throw new IOException("Failed to create folder " + compilerStateFolder.getAbsolutePath());
    }

    dexOutDir = new File(testingFolder, "outputBinary");
    if (!dexOutDir.exists() && !dexOutDir.mkdir()) {
      throw new IOException("Failed to create folder " + dexOutDir.getAbsolutePath());
    }
    dexFile = new File(dexOutDir, "classes.dex");
  }

  public void setOut(OutputStream out) {
    this.out = out;
  }

  public void setErr(OutputStream err) {
    this.err = err;
  }

  public void setIsApiTest() {
    isApiTest = true;
  }

  @Nonnull
  public File addJavaFile(@Nonnull String packageName, @Nonnull String fileName,
      @Nonnull String fileContent) throws IOException {
    File file = AbstractTestTools.createFile(sourceFolder, packageName, fileName, fileContent);
    javaFiles.add(file);
    return file;
  }

  public void deleteJavaFile(@Nonnull File javaFile)
      throws IOException {
    AbstractTestTools.deleteFile(javaFile);
    javaFiles.remove(javaFile);
  }

  @Nonnull
  public File getCompilerStateFolder() {
    return compilerStateFolder;
  }

  public void cleanSnapshot() {
    fileModificationDate.clear();
  }

  public void snapshotJackFilesModificationDate() throws LibraryIOException {
    InputJackLibrary compilerStateLib = null;
    try {
      compilerStateLib = AbstractTestTools.getInputJackLibrary(compilerStateFolder);
      Iterator<InputVFile> jayceIter = compilerStateLib.iterator(FileType.JAYCE);
      while (jayceIter.hasNext()) {
        InputVFile jayceFile = jayceIter.next();
        fileModificationDate.put(jayceFile.getPathFromRoot(),
            Long.valueOf(jayceFile.getLastModified()));
      }
    } finally {
      if (compilerStateLib != null) {
        compilerStateLib.close();
      }
    }
  }

  @Nonnull
  public List<String> getFQNOfRebuiltTypes() throws LibraryIOException {
    assert !fileModificationDate.isEmpty();

    List<String> fqnOfRebuiltTypes = new ArrayList<String>();
    InputJackLibrary compilerStateLib = null;
    try {
      compilerStateLib = AbstractTestTools.getInputJackLibrary(compilerStateFolder);
      Iterator<InputVFile> jayceIter = compilerStateLib.iterator(FileType.JAYCE);
      while (jayceIter.hasNext()) {
        InputVFile jayceFile = jayceIter.next();
        VPath path = jayceFile.getPathFromRoot();
        Long previousDate = fileModificationDate.get(path);
        if (previousDate == null || jayceFile.getLastModified() > previousDate.longValue()) {
          String fqnWithExtension = path.getPathAsString('.');
          String fqn = fqnWithExtension.substring(0,
              fqnWithExtension.lastIndexOf(JayceFileImporter.JAYCE_FILE_EXTENSION));
          fqnOfRebuiltTypes.add(fqn);
        }
      }
    } finally {
      if (compilerStateLib != null) {
        compilerStateLib.close();
      }
    }

    return fqnOfRebuiltTypes;
  }

  public void incrementalBuildFromFolder() throws Exception {
    incrementalBuildFromFolder(null, Collections.<File>emptyList());
  }

  public void incrementalBuildFromFolder(@Nonnull File[] classpath) throws Exception {
    incrementalBuildFromFolder(classpath, Collections.<File>emptyList());
  }

  public void incrementalBuildFromFolder(@CheckForNull File[] classpath,
      @Nonnull List<File> imports) throws Exception {
    incrementalBuildFromFolder(classpath, imports, MultiDexKind.NONE);
  }

  public void incrementalBuildFromFolder(@CheckForNull File[] classpath,
      @Nonnull List<File> imports, @Nonnull MultiDexKind multiDexKind) throws Exception {

    List<Class<? extends IToolchain>> excludeList = new ArrayList<Class<? extends IToolchain>>(1);
    excludeList.add(LegacyJillToolchain.class);
    excludeList.add(IncrementalToolchain.class);
    excludeList.add(TwoStepsToolchain.class);
    excludeList.add(JillBasedToolchain.class);
    if (isApiTest) {
      excludeList.add(JackCliToolchain.class);
    }

    JackBasedToolchain jackToolchain =
        AbstractTestTools.getCandidateToolchain(JackBasedToolchain.class, excludeList);
    jackToolchain.setIncrementalFolder(getCompilerStateFolder());
    jackToolchain.addStaticLibs(imports.toArray(new File[imports.size()]));
    jackToolchain.setMultiDexKind(multiDexKind);

    jackToolchain.setOutputStream(out);
    jackToolchain.setErrorStream(err);

    File[] bootclasspath = jackToolchain.getDefaultBootClasspath();

    jackToolchain.addToClasspath(bootclasspath);
    if (classpath != null) {
      jackToolchain.addToClasspath(classpath);
    }

    jackToolchain.srcToExe(dexOutDir, /* zipFile = */ false, sourceFolder);

    Thread.sleep(1000);
  }

  @Nonnull
  public void run(@Nonnull String mainClass, @Nonnull String expected) throws Exception {
    List<RuntimeRunner> runnerList = AbstractTestTools.listRuntimeTestRunners(null);
    for (RuntimeRunner runner : runnerList) {
      ByteArrayOutputStream out = new ByteArrayOutputStream();
      ((AbstractRuntimeRunner) runner).setOutputStream(out);
      Assert.assertEquals(0, runner.run(new String[0], mainClass, dexFile));
      Assert.assertEquals(expected, out.toString());
    }
  }

  @Nonnull
  public File getDexFile() {
    return dexFile;
  }

  @Nonnull
  public int getJayceCount() throws LibraryIOException {
    int size = 0;
    InputJackLibrary compilerStateLib = null;
    try {
      compilerStateLib = AbstractTestTools.getInputJackLibrary(compilerStateFolder);
      Iterator<InputVFile> jayceIter = compilerStateLib.iterator(FileType.JAYCE);
      while (jayceIter.hasNext()) {
        size++;
        jayceIter.next();
      }
    } finally {
      if (compilerStateLib != null) {
        compilerStateLib.close();
      }
    }
    return size;
  }
}
