package _VisualDVM.Passes.All;
import Common.Passes.Pass;
import Common.Passes.PassException;
import Common.Utils.Utils_;
import Common.Visual.Windows.Dialog.VDirectoryChooser;
import _VisualDVM.Constants;
import _VisualDVM.Global;
import _VisualDVM.Passes.PassCode;
import _VisualDVM.TestingSystem.Common.Group.Group;
import _VisualDVM.TestingSystem.Common.Test.Test;
import _VisualDVM.TestingSystem.Common.TestFile.TestFile;
import _VisualDVM.Utils;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.util.Arrays;
import java.util.Vector;
public class CreateTestFromDirectory extends Pass<Test> {
    Group group = null;
    File dir = null;
    boolean from_files_chooser = false;
    Vector<File> files = null;
    //--
    Vector<TestFile> testFiles = new Vector<>();
    @Override
    public String getIconPath() {
        return "/icons/OpenProject.png";
    }
    @Override
    public String getButtonText() {
        return "";
    }
    @Override
    protected boolean needsAnimation() {
        return true;
    }
    //--
    void saveDirectory() {
        Global.mainModule.getPass(PassCode.UpdateProperty).Do("ProjectsSearchDirectory",
                (dir.getParentFile() == null) ? dir.getAbsolutePath() : dir.getParent()
        );
    }
    protected boolean selectFiles() {
        VDirectoryChooser directoryChooser = new VDirectoryChooser("Выбор домашней папки теста");
        Utils.ChooserProjectsSearchDirectory(directoryChooser);
        dir = directoryChooser.ShowDialog();
        if (dir == null) {
            Log.Writeln_("Папка не выбрана.");
            return false;
        } else {
            files = new Vector<>(Arrays.asList(dir.listFiles()));
            saveDirectory();
        }
        return true;
    }
    protected boolean initTarget() throws Exception {
        target = new Test();
        target.sender_address = Global.mainModule.getAccount().email;
        target.sender_name = Global.mainModule.getAccount().name;
        target.group_id = group.id;
        target.description = dir.getName();
        return true;
    }
    @Override
    protected boolean canStart(Object... args) throws Exception {
        files = null;
        if (args.length == 0) {
            //--
            from_files_chooser = true;
            if (!Global.testingServer.db.groups.getUI().canModifyCurrent(Log)) {
                return false;
            }
            group = Global.testingServer.db.groups.getUI().getCurrent();
            if (!selectFiles())
                return false;
            //-
        } else {
            from_files_chooser = false;
            dir = (File) args[0];
            group = (Group) args[1];
            files = new Vector<>(Arrays.asList(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())
                    + " содержит запрещённые символы "
                    + Utils_.printAllForbiddenCharacters() + ", или кириллицу.");
            return false;
        }
        //--
        if (files == null) {
            Log.Writeln_("Не удалось получить список файлов для папки " + Utils_.Brackets(dir) + ".");
            return false;
        }
        //---
        testFiles = 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())) {
                //если файл. все недопустимые файлы просто игнорируются.
                TestFile testFile = new TestFile(file);
                if (isNotExcluded(testFile)) {
                    switch (testFile.fileType) {
                        case program:
                            if (testFile.languageName.equals(group.language)) {
                                active_programs++;
                                testFiles.add(testFile);
                            } else
                                other_project_files++;
                            break;
                        case header:
                            headers++;
                            testFiles.add(testFile);
                            break;
                        case none:
                            testFiles.add(testFile);
                            other_project_files++;
                            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 (testFiles.isEmpty()) {
            Log.Writeln_("В папке не найдено файлов с допустимыми расширениями для языка " +
                    group.language.getDescription() + "\n" +
                    group.language.PrintExtensions()
            );
        }
        //----
        if (!initTarget()) return false;
        //----
        target.files = new Vector<>(testFiles);
        return true;
    }
    public boolean isNotExcluded(TestFile testFile) {
        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 (TestFile testFile : testFiles) {
            File src = new File(dir, testFile.name);
            File dst = new File(tempProject, testFile.name);
            FileUtils.copyFile(src, dst);
        }
        target.files = new Vector<>();
        target.files.addAll(testFiles);
        //---
        Utils.ClearProjectData(tempProject);
        //--
        ZipFolderPass zip = new ZipFolderPass();
        if (zip.Do(tempProject.getAbsolutePath(), tempArchive.getAbsolutePath())) {
            target.project_archive_bytes = Utils_.fileToBytes(tempArchive);
        } else throw new PassException("Не удалось создать архив папки с кодом.");
        return tempProject;
    }
    //-
    @Override
    protected void body() throws Exception {
        ShowMessage1(dir.getName());
        File tempProject = packTestCode(); //создание копии папки, и архивация.
    }
    @Override
    protected boolean validate() {
        return Log.isEmpty();
    }
    @Override
    protected void performDone() throws Exception {
        super.performDone();
        if (from_files_chooser)
            Global.mainModule.getPass(PassCode.PublishTest).Do(target);
    }
}
