package _VisualDVM.GlobalData.Compiler;
import Common.Utils.Utils_;
import Common.Visual.UI_;
import _VisualDVM.Current;
import Common.Visual.DataSetControlForm;
import _VisualDVM.Global;
import _VisualDVM.Visual.UI;
import Common.Visual.Windows.Dialog.DBObjectDialog;
import _VisualDVM.Utils;
import _VisualDVM.Validators.PathValidator;
import Common.Database.Objects.DBObject;
import Common.Database.Tables.FKBehaviour;
import Common.Database.Tables.FKCurrentObjectBehaviuor;
import Common.Database.Tables.FKDataBehaviour;
import Common.Database.Tables.iDBTable;
import _VisualDVM.GlobalData.Compiler.UI.CompilerFields;
import _VisualDVM.GlobalData.Makefile.Makefile;
import _VisualDVM.GlobalData.Module.Module;
import _VisualDVM.GlobalData.RunConfiguration.RunConfiguration;

import java.util.LinkedHashMap;
public class CompilersDBTable extends iDBTable<Compiler> {
    public CompilersDBTable() {
        super(Compiler.class);
    }
    @Override
    public String getSingleDescription() {
        return "компилятор";
    }
    @Override
    public String getPluralDescription() {
        return "компиляторы";
    }
    @Override
    public LinkedHashMap<Class<? extends DBObject>, FKBehaviour> getFKDependencies() {
        LinkedHashMap<Class<? extends DBObject>, FKBehaviour> res = new LinkedHashMap<>();
        res.put(Makefile.class, new FKBehaviour(FKDataBehaviour.DROP, FKCurrentObjectBehaviuor.PASSIVE));
        res.put(Module.class, new FKBehaviour(FKDataBehaviour.DROP, FKCurrentObjectBehaviuor.PASSIVE));
        res.put(RunConfiguration.class, new FKBehaviour(FKDataBehaviour.DROP, FKCurrentObjectBehaviuor.PASSIVE));
        return res;
    }
    @Override
    public DBObjectDialog<Compiler, CompilerFields> getDialog() {
        return new DBObjectDialog<Compiler, CompilerFields>(CompilerFields.class) {
            @Override
            public void validateFields() {
                //<editor-fold desc="расположение">
                String home = fields.tfHome.getText();
                if (!home.isEmpty()) {
                    if (home.startsWith("/")) {
                        if (Utils_.ContainsCyrillic(home))
                            Log.Writeln("Расположение компилятора не может содержать кириллицу");
                        else {
                            new PathValidator(home, "Расположение компилятора", Log).Validate();
                        }
                    } else
                        Log.Writeln("Расположение компилятора может быть либо пустой строкой, либо путём к файлу");
                }
                //</editor-fold>
                //<editor-fold desc="команда вызова">
                String call_command = fields.tfCallCommand.getText();
                if (call_command.isEmpty())
                    Log.Writeln("Команда вызова компилятора не может быть пустой");
                else if (Utils_.ContainsCyrillic(call_command))
                    Log.Writeln("Команда вызова компилятора не может содержать кириллицу");
                else {
                    switch (call_command.charAt(0)) {
                        case ' ':
                            Log.Writeln("Команда вызова компилятора не может начинаться с пробела.");
                            break;
                        case '/':
                            if (call_command.endsWith("/"))
                                Log.Writeln("Каталог не может быть указан в качестве команды.");
                            else
                                new PathValidator(call_command, "Команда вызова компилятора", Log).Validate();
                            break;
                        default:
                            //это команда.
                            //самое опасное место. теоретически тут можно ввести любую команду ОС, в том числе rm -rf
                            if (call_command.contains(" "))
                                Log.Writeln("Прямая команда вызова не может содержать пробелы");
                            if (!call_command.contains("+")&& Utils_.ContainsForbiddenName(call_command))
                                Log.Writeln("Прямая команда вызова содержит запрещённые символы");
                            else {
                                if (Utils.isLinuxSystemCommand(call_command))
                                    Log.Writeln(Utils_.DQuotes(call_command) + " является системной командой Linux");
                            }
                            break;
                    }
                }
                //</editor-fold>
            }
            @Override
            public void fillFields() {
                fields.tfDescription.setText(Result.description);
                fields.tfCallCommand.setText(Result.call_command);
                fields.tfHelpCommand.setText(Result.help_command);
                fields.tfVersionCommand.setText(Result.version_command);
                fields.tfHome.setText(Result.home_path);
                UI_.TrySelect(fields.cbCompilerType, Result.type);
                fields.events_on = true;
            }
            @Override
            public void ProcessResult() {
                Result.machine_id = Global.mainModule.getMachine().id;
                Result.description = fields.tfDescription.getText();
                Result.call_command = fields.tfCallCommand.getText();
                Result.help_command = fields.tfHelpCommand.getText();
                Result.version_command = fields.tfVersionCommand.getText();
                Result.home_path = fields.tfHome.getText();
                Result.type = (CompilerType) fields.cbCompilerType.getSelectedItem();
            }
            @Override
            public int getDefaultHeight() {
                return 300;
            }
        };
    }
    @Override
    protected DataSetControlForm createUI() {
        return new DataSetControlForm(this){
            @Override
            protected void AdditionalInitColumns() {
                columns.get(0).setVisible(false);
            }
            @Override
            public void ShowCurrentObject() throws Exception {
                super.ShowCurrentObject();
                UI.getMainWindow().getTestingWindow().ShowCurrentCompiler();
            }
            @Override
            public void ShowNoCurrentObject() throws Exception {
                super.ShowNoCurrentObject();
                UI.getMainWindow().getTestingWindow().ShowCurrentCompiler();
            }
        };
    }
    @Override
    public String[] getUIColumnNames() {
        return new String[]{"описание", "команда вызова", "версия", "ревизия"};
    }
    @Override
    public Object getFieldAt(Compiler object, int columnIndex) {
        switch (columnIndex) {
            case 1:
                return object.description;
            case 2:
                return object.call_command;
            case 3:
                return object.version;
            case 4:
                return object.revision;
        }
        return null;
    }
    @Override
    public Current CurrentName() {
        return Current.Compiler;
    }
}
