package jetbrains.mps.build.ant;

/*Generated by MPS */

import jetbrains.mps.annotations.GeneratedClass;
import jetbrains.mps.tool.common.MigrateTaskProperties;
import java.io.File;
import org.apache.tools.ant.types.DirSet;
import org.apache.tools.ant.types.Resource;
import org.apache.tools.ant.types.resources.FileProvider;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.BuildException;
import java.util.Properties;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.Objects;
import java.util.Set;
import java.util.LinkedHashSet;

@GeneratedClass(node = "r:7b2ffdb7-2bfc-4488-8c0c-ee8fe93fe3c1(jetbrains.mps.build.ant)/108194650710656503", model = "r:7b2ffdb7-2bfc-4488-8c0c-ee8fe93fe3c1(jetbrains.mps.build.ant)")
public class MigrationTask extends MpsLoadTask {

  private final MigrateTaskProperties myProps;

  public MigrationTask() {
    super("jetbrains.mps.build.migration.MigrationWorker");
    // generally, this task is executed with without explicit fork="true", with default MpsLoadTask.myFork == true.
    myProps = new MigrateTaskProperties(myWhatToDo).setPreCheckFailureHalt(true).setHaltOnDependencyError(true).setMakeDistribModules(true);
    // makeDistribModules==true here is for backwards compatibility
    setFailOnError(true);
    setOpenPackages(true);
    setJnaLibraryPath(DEFAULT_JNA_LIBRARY_PATH);
  }

  public void setProject(String project) {
    File file = new File(project);
    if (checkProperProjectDir(file)) {
      myWhatToDo.addProjectFile(file);
    }
  }

  public void addConfigured(ProjectPath projectPath) {
    if (checkProperProjectDir(projectPath.getPath())) {
      myWhatToDo.addProjectFile(projectPath.getPath());
    }
  }

  public void addConfigured(DirSet projectDirs) {
    for (Resource res : projectDirs) {
      if (res.isDirectory() && res.isExists() && res instanceof FileProvider) {
        File dir = ((FileProvider) res).getFile();
        if (checkProperProjectDir(dir)) {
          myWhatToDo.addProjectFile(dir);
        }
      } else {
        getProject().log(String.format("Resource %s not recognized as a project directory", res), Project.MSG_INFO);
      }
    }
  }

  private boolean checkProperProjectDir(File dir) {
    if (new File(dir, ".mps").exists()) {
      return true;
    }
    getProject().log(String.format("Not an MPS project: %s", dir), Project.MSG_WARN);
    return false;
  }

  public void setHaltOnPrecheckFailure(boolean haltOnPrecheckFailure) {
    myProps.setPreCheckFailureHalt(haltOnPrecheckFailure);
  }

  public void setHaltOnDependencyError(boolean haltOnDependencyError) {
    myProps.setHaltOnDependencyError(haltOnDependencyError);
  }

  public void setMakeDistribModules(boolean makeDistrib) {
    myProps.setMakeDistribModules(makeDistrib);
  }

  /**
   * force flag ignores the marker files for projects which allow pending migrations, migrating them anyway
   */
  public void setForce(boolean value) {
    myProps.setForceFlag(value);
  }

  @Override
  public void execute() throws BuildException {
    final File propFile = new File(getProject().getBaseDir(), "migration_result.properties");
    propFile.deleteOnExit();
    final String errCodeKey = "mps.migration.errcode";
    myProps.setOutputPropertyFile(propFile).setOutputPropertyErrorKey(errCodeKey);

    super.execute();
    Properties p = new Properties();
    try (FileInputStream fis = new FileInputStream(propFile)) {
      p.load(fis);
    } catch (IOException e) {
      throw new BuildException("can't read task output from " + propFile, e);
    }
    if (!(Objects.equals(p.getProperty(errCodeKey), "0"))) {
      throw new BuildException("Migration was not executed. See log for details.");
    }
  }

  @Override
  protected Set<File> calculateClassPath(boolean fork) {
    Set<File> classPath = new LinkedHashSet<File>(super.calculateClassPath(fork));

    File mpsHome = getMpsHome_Checked();

    // j.m.build.migration.jar hosts MigrationWorker
    addClassPath(classPath, mpsHome, "/plugins/mps-build/languages/build/jetbrains.mps.build.migration.jar");
    // note, unlike migration and modelchecker plugins, I intentionally do not add mps-build as a plugin to myWhatToDo
    // as the only purpose of the jar in classpath is to load MigrationWorker class. Indeed, with "all plugins in global classpath"
    // approach, adding it as a plugin would work, but, for one, I intend to change this approach, and, for two, I don't think complete
    // mps-build plugin is always necessary. Last but not least, j.m.build.migration module presents itself as a regular ModuleClassLoader-backed module
    // although in fact it's pure java "get me in global cp" class.

    return classPath;
  }

  private void addClassPath(Set<File> classPath, File mpsHome, String relativePath) {
    File cp = new File(mpsHome, relativePath);
    assert cp.exists() : "requested file does not exist: " + cp.getAbsolutePath();
    classPath.add(cp);
  }
}
