package _VisualDVM.TestingSystem.SAPFOR.Json;
import Common.Utils.Utils_;
import _VisualDVM.ComponentsServer.Component.Sapfor.Sapfor;
import _VisualDVM.Constants;
import _VisualDVM.ProjectData.Files.DBProjectFile;
import _VisualDVM.ProjectData.Files.FileType;
import _VisualDVM.ProjectData.Files.ProjectFile;
import _VisualDVM.ProjectData.LanguageName;
import _VisualDVM.ProjectData.Messages.FileMessagesJson;
import _VisualDVM.ProjectData.Messages.Message;
import _VisualDVM.ProjectData.Messages.MessagesJson;
import _VisualDVM.ProjectData.Project.db_project_info;
import _VisualDVM.TestingSystem.SAPFOR.SapforTask.SapforTask;
import com.google.gson.annotations.Expose;
import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.Serializable;
import java.nio.charset.Charset;
import java.nio.file.Paths;
import java.util.LinkedHashMap;
import java.util.Vector;
public class SapforVersion_json implements Serializable {
    @Expose
    public String version = "";
    @Expose
    public String description = "";
    @Expose
    public SapforVersionState state = null;
    //поля для отображения деревьев.
    public File Home = null;
    public LinkedHashMap<String, ProjectFile> files = new LinkedHashMap<>();
    //--
    public ProjectFile parse_out = null;
    public ProjectFile parse_err = null;
    public ProjectFile out = null;
    public ProjectFile err = null;
    //--
    public SapforTask task = null; //родная задача. Нужна для построения дерева версий.
    public db_project_info project = null;
    //--
    public VersionComparisonState comparisonState = VersionComparisonState.Unknown;
    //--
    public SapforVersion_json(String version_in, String description_in) {
        version = version_in;
        description = description_in;
    }
    public SapforVersion_json(String root_in, String version_in, String description_in) {
        version = version_in.substring(root_in.length() + 1);
        description = description_in;
    }
    public void getFiles(File configurationRoot) {
        //--
        comparisonState = VersionComparisonState.Unknown;
        //--
        String relativePath = Utils_.isWindows() ? Utils_.toW(version) : version;
        Home = Paths.get(configurationRoot.getAbsolutePath(), relativePath).toFile();
        files = new LinkedHashMap<>();
        //--
        File[] files_ = Home.listFiles();
        if (files_ != null) {
            for (File file : files_) {
                if (file.isFile()) {
                    ProjectFile projectFile = new ProjectFile(file);
                    if (!projectFile.fileType.equals(FileType.forbidden)
                    ) {
                        files.put(projectFile.file.getName(), projectFile);
                    }
                }
            }
        }
        parse_out = new ProjectFile(Paths.get(Home.getAbsolutePath(), Constants.data, Constants.parse_out_file).toFile());
        parse_err = new ProjectFile(Paths.get(Home.getAbsolutePath(), Constants.data, Constants.parse_err_file).toFile());
        out = new ProjectFile(Paths.get(Home.getAbsolutePath(), Constants.data, Constants.out_file).toFile());
        err = new ProjectFile(Paths.get(Home.getAbsolutePath(), Constants.data, Constants.err_file).toFile());
        //--
    }
    public void getFilesAndCheckState(File configurationRoot) {
        //--
        state = SapforVersionState.Empty;
        //--
        String relativePath = Utils_.isWindows() ? Utils_.toW(version) : version;
        Home = Paths.get(configurationRoot.getAbsolutePath(), relativePath).toFile();
        files = new LinkedHashMap<>();
        //--
        File[] files_ = Home.listFiles();
        if (files_ != null) {
            for (File file : files_) {
                if (file.isFile()) {
                    ProjectFile projectFile = new ProjectFile(file);
                    if (!projectFile.fileType.equals(FileType.forbidden)
                    ) {
                        files.put(projectFile.file.getName(), projectFile);
                    }
                }
            }
            if (!files.isEmpty())
                state = SapforVersionState.Normal;
        }
        parse_out = new ProjectFile(Paths.get(Home.getAbsolutePath(), Constants.data, Constants.parse_out_file).toFile());
        parse_err = new ProjectFile(Paths.get(Home.getAbsolutePath(), Constants.data, Constants.parse_err_file).toFile());
        out = new ProjectFile(Paths.get(Home.getAbsolutePath(), Constants.data, Constants.out_file).toFile());
        err = new ProjectFile(Paths.get(Home.getAbsolutePath(), Constants.data, Constants.err_file).toFile());
        //--
        Vector<File> out_files = new Vector<>();
        out_files.add(parse_out.file);
        out_files.add(parse_err.file);
        out_files.add(out.file);
        out_files.add(err.file);
        //--
        for (File file : out_files) {
            try {
                if (file.exists()) {
                    Vector<String> lines = new Vector<>(FileUtils.readLines(file));
                    if (!Sapfor.checkLines(lines)) {
                        state = SapforVersionState.HasErrors;
                        return;
                    }
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
    public boolean isMatch(SapforVersion_json version_json) {
        if (!description.equals(version_json.description)) {
            return false;
        }
        if (files.size() != version_json.files.size()) {
            return false;
        }
        for (String name1 : files.keySet()) {
            if (!version_json.files.containsKey(name1)) {
                return false;
            }
        }
        for (String name1 : files.keySet()) {
            ProjectFile file1 = files.get(name1);
            ProjectFile file2 = version_json.files.get(name1);
            //---
            String text1 = "";
            String text2 = "";
            try {
                text1 = FileUtils.readFileToString(file1.file, Charset.defaultCharset());
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            try {
                text2 = FileUtils.readFileToString(file2.file, Charset.defaultCharset());
            } catch (Exception ex) {
                ex.printStackTrace();
            }
            if (!text1.equalsIgnoreCase(text2))
                return false;
        }
        return true;
    }
    public void createProject(File rootHome) throws Exception {
        project = null;
        String version_ = Utils_.isWindows() ? Utils_.toW(version) : Utils_.toU(version);
        project = new db_project_info();
        project.Home = Paths.get(rootHome.getAbsolutePath(), version_).toFile();
        project.name = project.Home.getName();
        project.description = description;
        project.languageName = LanguageName.fortran;
        project.creationDate = Utils_.getDateNumber();
        //---
        FileUtils.copyDirectory(Home, project.Home);
        ///--------------------------------------
        project.CreateVisualiserData();
    }
    public void ReadMessages() throws Exception {
        if (project != null) {
            //--
            File p_out = Paths.get(project.Home.getAbsolutePath(), Constants.data, Constants.parse_out_file).toFile();
            File p_err = Paths.get(project.Home.getAbsolutePath(), Constants.data, Constants.parse_err_file).toFile();
            File out = Paths.get(project.Home.getAbsolutePath(), Constants.data, Constants.out_file).toFile();
            File err = Paths.get(project.Home.getAbsolutePath(), Constants.data, Constants.err_file).toFile();
            File messages_dump = Paths.get(project.Home.getAbsolutePath(), Constants.data, "error_messages.json").toFile();
            MessagesJson messagesJson = null;
            //--
            if (p_out.exists()) {
                project.Log += (FileUtils.readFileToString(p_out));
            }
            if (out.exists()) {
                project.Log += "\n" + FileUtils.readFileToString(out);
            }
            //в потоки ошибок идет информация от операционной системы. сообщений там быть не должно.
            if (p_err.exists())
                project.Log += (FileUtils.readFileToString(p_err));
            if (err.exists())
                project.Log += "\n" + FileUtils.readFileToString(err);
            //--
            if (messages_dump.exists()) {
                try {
                    String packed = FileUtils.readFileToString(messages_dump);
                    messagesJson = Utils_.gson.fromJson(packed, MessagesJson.class);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
            project.Open();
            project.Update(); //Журнал
            //а так же, убрать dep и txt
            if (messagesJson != null) {
                project.db.BeginTransaction();
                //-
                for (FileMessagesJson fileMessagesJson : messagesJson.allMessages) {
                    fileMessagesJson.file = Utils_.toW(fileMessagesJson.file);
                    //--
                    DBProjectFile file = project.db.files.Data.get(fileMessagesJson.file);
                    for (Message message : fileMessagesJson.messages) {
                        file.CreateAndAddNewMessage(1, message.value, message.line, message.group);
                    }
                    //update file
                    project.db.Update(file);
                }
                project.db.Commit();
            }
            project.db.Disconnect();
        }
    }
    @Override
    public String toString() {
        return Home.getName() + " : " + Utils_.Brackets(description) + " файлы: " + files.size();
    }
}
