package Visual_DVM_2021.Passes.All;
import Common.Constants;
import Common.Current;
import Common.Utils.Files.VDirectoryChooser;
import Common.Utils.Utils;
import GlobalData.Settings.SettingName;
import ProjectData.Files.ProjectFile;
import ProjectData.LanguageName;
import Repository.Component.Sapfor.Sapfor;
import TestingSystem.Common.Group.Group;
import TestingSystem.Common.Test.Test;
import Visual_DVM_2021.Passes.PassCode_2021;
import Visual_DVM_2021.Passes.PassException;
import Visual_DVM_2021.Passes.Pass_2021;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.util.Vector;
public class CreateTestFromDirectory extends Pass_2021<Test> {
    VDirectoryChooser directoryChooser = new VDirectoryChooser("Выбор домашней папки теста");
    @Override
    public String getIconPath() {
        return "/icons/OpenProject.png";
    }
    @Override
    public String getButtonText() {
        return "";
    }
    @Override
    protected boolean needsAnimation() {
        return true;
    }
    Group group = null;
    File dir = null;
    boolean from_directory_chooser = false;
    Vector<ProjectFile> project_files = new Vector<>();
    @Override
    protected boolean canStart(Object... args) throws Exception {
        if (args.length == 0) {
            from_directory_chooser = true;
            if (!Current.Check(Log, Current.Group))
                return false;
            Utils.RestoreSelectedDirectory(directoryChooser);
            dir = directoryChooser.ShowDialog();
            group = Current.getGroup();
            if (dir == null) {
                Log.Writeln_("Папка не выбрана.");
                return false;
            } else {
                Pass_2021.passes.get(PassCode_2021.UpdateSetting).Do(SettingName.ProjectsSearchDirectory, dir.getParent());
            }
        } else {
            from_directory_chooser = false;
            dir = (File) args[0];
            group = (Group) args[1];
        }
        //---
        File[] files = dir.listFiles();
        int subdirs = 0;
        int bad = 0;
        int active_programs = 0;
        int headers = 0;
        int other_project_files = 0;
        //---
        if (dir.getName().equalsIgnoreCase(Constants.data)) {
            Log.Writeln_("Папка " + Utils.Brackets(dir) + " является служебной папкой визуализатора.");
            return false;
        }
        //--
        if (Utils.ContainsCyrillic(dir.getName()) || Utils.ContainsForbiddenName(dir.getName())) {
            Log.Writeln_("Имя папки " + Utils.Brackets(dir.getName()) + " содержит запрещённые символы " + Constants.all_forbidden_characters_string + ", или кириллицу.");
            return false;
        }
        //--
        if (files == null) {
            Log.Writeln_("Не удалось получить список файлов для папки " + Utils.Brackets(dir) + ".");
            return false;
        }
        //---
        project_files = new Vector<>();
        //--
        for (File file : files) {
            //-----
            if (file.isDirectory()) {
                //если это подпапка нам все равно на каком она языке. не версия и не служебная. ее наличие уже не допустимо.
                if (!file.getName().equalsIgnoreCase(Constants.data) &&
                        !Utils.isVersion(file)) {
                    subdirs++;
                }
            } else if (file.isFile() && !Utils.ContainsCyrillic(file.getName()) && !Utils.ContainsForbiddenName(file.getName())) {
                //если файл. все недопустимые файлы просто игнорируются.
                ProjectFile projectFile = new ProjectFile(file);
                if (isNotExcluded(projectFile)) {
                    switch (projectFile.fileType) {
                        case program:
                            if (projectFile.languageName.equals(group.language)) {
                                active_programs++;
                                project_files.add(projectFile);
                            } else
                                other_project_files++;
                            break;
                        case header:
                            headers++;
                            project_files.add(projectFile);
                            break;
                        default:
                            other_project_files++;
                            break;
                    }
                }
            }
        }
        //--
        if (subdirs > 0) {
            Log.Writeln_("Папка " + Utils.Brackets(dir) + " содержит вложенные подпапки,\n" +
                    "не являющиеся версиями или данными визуализатора");
            return false;
        }
        if (active_programs == 0) {
            Log.Writeln_("Папка не содержит ни одной программы на языке " + group.language.getDescription() + ".");
            return false;
        }
        if (project_files.isEmpty()) {
            Log.Writeln_("В папке не найдено файлов с допустимыми расширениями для языка " +
                    group.language.getDescription() + "\n" +
                    group.language.PrintExtensions()
            );
        }
        //-----
        target = new Test();
        target.sender_address = Current.getAccount().email;
        target.sender_name = Current.getAccount().name;
        target.group_id = group.id;
        target.description = dir.getName();
        Vector<String> filesNames = new Vector<>();
        for (ProjectFile projectFile : project_files)
            filesNames.add(projectFile.file.getName());
        target.files = String.join("\n", filesNames);
        return true;
    }
    public boolean isNotExcluded(ProjectFile projectFile) {
        return true;
    }
    //-
    public File packTestCode() throws Exception {
        target.temp_project_name = Utils.getDateName("test");
        //-
        File tempProject = target.getTempProject();
        File tempArchive = target.getTempArchive();
        //- создать бд.
        FileUtils.forceMkdir(tempProject);
        //--
        for (ProjectFile projectFile : project_files) {
            System.out.println(projectFile.file.getAbsolutePath());
            File dst = new File(tempProject, projectFile.file.getName());
            FileUtils.copyFile(projectFile.file, dst);
        }
        //---
        Utils.ClearProjectData(tempProject);
        //--
        ZipFolderPass zip = new ZipFolderPass();
        if (zip.Do(tempProject.getAbsolutePath(), tempArchive.getAbsolutePath())) {
            target.project_archive_bytes = Utils.packFile(tempArchive);
        } else throw new PassException("Не удалось создать архив папки с кодом.");
        return tempProject;
    }
    //-
    @Override
    protected void body() throws Exception {
        ShowMessage1(dir.getName());
        //--
        File tempProject = packTestCode(); //создание копии папки, и архивация.
        //-- получить размерность консольным сапфором. папка уже отправлена и чистить ее не нужно!!
        ShowMessage2("Синтаксический анализ и определение размерности");
        if (group.language == LanguageName.fortran) {//если не определит, будут нули.
            Sapfor.getMinMaxDim(Sapfor.getTempCopy(Current.getSapfor().getFile()), tempProject, target);
        }
    }
    @Override
    protected boolean validate() {
        return Log.isEmpty();
    }
    @Override
    protected void performDone() throws Exception {
        super.performDone();
        if (from_directory_chooser)
            passes.get(PassCode_2021.PublishTest).Do(target);
    }
}
