package _VisualDVM.GlobalData.Tasks.Supervisor.Local;
import Common.CommonConstants;
import Common.Passes.Pass;
import Common.Utils.Utils_;
import _VisualDVM.Constants;
import _VisualDVM.GlobalData.Tasks.RunTask.RunTask;
import _VisualDVM.GlobalData.Tasks.Supervisor.TaskSupervisor;
import _VisualDVM.GlobalData.Tasks.Task;
import _VisualDVM.GlobalData.Tasks.TaskState;
import _VisualDVM.Utils;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.Map;
import java.util.Vector;
//про mpi mpich2
//https://stackoverflow.com/questions/12983635/how-to-include-library-mpich2-in-mingw
public abstract class LocalTaskSupervisor<T extends Task> extends TaskSupervisor<T, Pass> {
    protected Process taskProcess;
    protected int exitCode;
    @Override
    protected void StartTask() throws Exception {
        exitCode = CommonConstants.Nan;
        taskProcess = Utils.startScript(task.getLocalWorkspace(), getProjectCopy(), "start_task_script", getScriptText(), getEnvs());
        task.state = TaskState.Running;
    }
    @Override
    protected void AbortTask() throws Exception {
        Process killer = Runtime.getRuntime().exec(getKillCommand());
        killer.waitFor();
    }
    //---->
    protected abstract String getScriptText();
    protected abstract String getKillCommand();
    //----->
    protected Map<String, String> getEnvs() {
        return null;
    }
    //---->
    protected File getProjectCopy() {
        return Paths.get(task.getUser().getLocalProjectsDir().getAbsolutePath(), project.getUniqKey()).toFile();
    }
    protected File getBinary() {
        return Paths.get(getProjectCopy().getAbsolutePath(), "0" + (Utils_.isWindows() ? ".exe" : "")).toFile();
    }
    protected File getProjectOutput() {
        return Paths.get(getProjectCopy().getAbsolutePath(), Constants.out_file).toFile();
    }
    protected File getProjectErrors() {
        return Paths.get(getProjectCopy().getAbsolutePath(), Constants.err_file).toFile();
    }
    @Override
    protected void PrepareWorkspace() throws Exception {
        super.PrepareWorkspace(); //локальная подготовка
        Utils_.forceDeleteWithCheck(getProjectOutput());
        Utils_.forceDeleteWithCheck(getProjectErrors());
    }
    @Override
    protected void AchieveResults() throws Exception {
        Files.copy(getProjectOutput().toPath(), task.getOutputFile().toPath(), StandardCopyOption.REPLACE_EXISTING);
        Files.copy(getProjectErrors().toPath(), task.getErrorsFile().toPath(), StandardCopyOption.REPLACE_EXISTING);
    }
    protected void AchieveRunTaskResults(RunTask rTask) throws Exception {
        rTask.parseCleanTime();
        //-статистика
        Vector<File> stsFiles = new Vector<>();
        Utils.getFilesByExtensions_r(getProjectCopy(), stsFiles, "gz+");
        if (stsFiles.size() > 0) {
            File file = stsFiles.get(0);
            rTask.UpdateLastStsName(file.getName());
            Files.copy(file.toPath(), rTask.getLocalStsFile().toPath(), StandardCopyOption.REPLACE_EXISTING);
            rTask.hasDvmSts = true;
        }
        /*
        //-gcov
        if (rTask.getRunConfiguration().needsGCOV()) {
            //-
            Process gcovProcess = Utils.startScript(rTask.getLocalWorkspace(), getProjectCopy(), "gcov_script", "gcov *.gcda -p");
            gcovProcess.waitFor();
            //-
            project.CreateGCOVDirs();
            Vector<File> gcovs = new Vector<>();
            Utils.getFilesByExtensions_r(getProjectCopy(), gcovs, "gcov");
            for (File src : gcovs) {
                File dst = Paths.get(project.getGCOVDirectory().getAbsolutePath(),
                        src.getName().replace("#",
                                Global.isWindows ? "\\" : "/")).toFile();
                Files.move(src.toPath(), dst.toPath(), StandardCopyOption.REPLACE_EXISTING);
            }
        }
         */
    }
    protected void PrepareRunTaskWorkspace(RunTask rTask) throws Exception {
        Utils.deleteFilesByExtensions(getProjectCopy(), "gcda", "gcov", "gz+", "par");
        rTask.UpdateLastStsName("");
        //отправить usr.par.
        if (rTask.hasDVMPar()) {
            File par_text = Paths.get(getProjectCopy().getAbsolutePath(), "usr.par").toFile();
            FileUtils.write(par_text, String.join("\n", rTask.getRunConfiguration().getParList()));
        }
    }
    protected String getCoupDeGrace() {
        return "";
    }
}
