package _VisualDVM.ProjectData.SapforData;
import Common.Properties;
import Common.Utils.Vector_;
import _VisualDVM.ComponentsServer.BugReport.BugReport;
import _VisualDVM.ComponentsServer.BugReportSetting.BugReportSetting;
import _VisualDVM.Global;
import _VisualDVM.GlobalData.SapforProfileSetting.SapforProfileSetting;
import _VisualDVM.Passes.PassCode;
import com.google.gson.annotations.Expose;

import javax.swing.*;
import java.io.File;
import java.lang.reflect.Field;
import java.util.LinkedHashMap;
import java.util.Vector;
public class SapforProperties extends Properties {
    //настройки для компонента SAPFOR
    @Expose
    public boolean STATIC_SHADOW_ANALYSIS = false;
    @Expose
    public boolean STATIC_PRIVATE_ANALYSIS = true;//выключено
    @Expose
    public boolean FREE_FORM = false;
    @Expose
    public boolean KEEP_DVM_DIRECTIVES = false;
    @Expose
    public boolean KEEP_SPF_DIRECTIVES = false;
    @Expose
    public boolean PARALLELIZE_FREE_LOOPS = false; //выключено
    @Expose
    public int MAX_SHADOW_WIDTH = 50;
    @Expose
    public boolean OUTPUT_UPPER = false;
    @Expose
    public boolean TRANSLATE_MESSAGES = true;
    @Expose
    public boolean KEEP_LOOPS_CLOSE_NESTING = false;
    @Expose
    public boolean KEEP_GCOV = false;
    @Expose
    public String ANALYSIS_OPTIONS = " ";
    @Expose
    public boolean DEBUG_PRINT_ON = false;
    @Expose
    public boolean MPI_PROGRAM = false;
    @Expose
    public boolean IGNORE_IO_SAPFOR = false;
    @Expose
    public boolean KEEP_SPF_DIRECTIVES_AMONG_TRANSFORMATIONS = false;
    @Expose
    public boolean PARSE_FOR_INLINE = false; //не видимая
    //побочные настройки визулизатора
    @Expose
    public boolean Precompilation = true;
    @Expose
    public boolean SaveModifications = true; // сохранять исходную версию
    @Expose
    public int GCOVLimit = 10;
    @Expose
    public String DVMConvertationOptions = " ";
    //-
    public SapforProperties(File file_in) {
        super(file_in);
    }
    public SapforProperties() {
    }
    public SapforProperties(SapforProperties src) {
        this.Precompilation = src.Precompilation;
        this.SaveModifications = src.SaveModifications; // сохранять исходную версию
        this.GCOVLimit = src.GCOVLimit;
        this.DVMConvertationOptions = src.DVMConvertationOptions;
        //настройки для компонента SAPFOR
        this.STATIC_SHADOW_ANALYSIS = src.STATIC_SHADOW_ANALYSIS;
        this.STATIC_PRIVATE_ANALYSIS = src.STATIC_PRIVATE_ANALYSIS;
        this.FREE_FORM = src.FREE_FORM;
        this.KEEP_DVM_DIRECTIVES = src.KEEP_DVM_DIRECTIVES;
        this.KEEP_SPF_DIRECTIVES = src.KEEP_SPF_DIRECTIVES;
        this.PARALLELIZE_FREE_LOOPS = src.PARALLELIZE_FREE_LOOPS;
        this.MAX_SHADOW_WIDTH = src.MAX_SHADOW_WIDTH;
        this.OUTPUT_UPPER = src.OUTPUT_UPPER;
        this.TRANSLATE_MESSAGES = src.TRANSLATE_MESSAGES;
        this.KEEP_LOOPS_CLOSE_NESTING = src.KEEP_LOOPS_CLOSE_NESTING;
        this.KEEP_GCOV = src.KEEP_GCOV;
        this.ANALYSIS_OPTIONS = src.ANALYSIS_OPTIONS;
        this.DEBUG_PRINT_ON = src.DEBUG_PRINT_ON;
        this.MPI_PROGRAM = src.MPI_PROGRAM;
        this.IGNORE_IO_SAPFOR = src.IGNORE_IO_SAPFOR;
        this.KEEP_SPF_DIRECTIVES_AMONG_TRANSFORMATIONS = src.KEEP_SPF_DIRECTIVES_AMONG_TRANSFORMATIONS;
        this.PARSE_FOR_INLINE = src.PARSE_FOR_INLINE;
    }
    public String pack() {
        Vector<String> res = new Vector_<String>(
                STATIC_SHADOW_ANALYSIS ? "1" : "0",
                STATIC_PRIVATE_ANALYSIS ? "1" : "0",
                FREE_FORM ? "1" : "0",
                KEEP_DVM_DIRECTIVES ? "1" : "0",
                KEEP_SPF_DIRECTIVES ? "1" : "0",
                PARALLELIZE_FREE_LOOPS ? "1" : "0",
                String.valueOf(MAX_SHADOW_WIDTH),
                OUTPUT_UPPER ? "1" : "0",
                TRANSLATE_MESSAGES ? "1" : "0",
                KEEP_LOOPS_CLOSE_NESTING ? "1" : "0",
                KEEP_GCOV ? "1" : "0",
                ANALYSIS_OPTIONS,
                DEBUG_PRINT_ON ? "1" : "0",
                MPI_PROGRAM ? "1" : "0",
                IGNORE_IO_SAPFOR ? "1" : "0",
                KEEP_SPF_DIRECTIVES_AMONG_TRANSFORMATIONS ? "1" : "0",
                PARSE_FOR_INLINE ? "1" : "0"
        );
        return String.join("|", res);
    }
    //-
    @Override
    public String getFieldDescription(String fieldName) {
        switch (fieldName) {
            case "SaveModifications":
                return "Сохранять копию исходной версии при преобразованиях";
            case "DVMConvertationOptions":
                return "Опции DVM конвертации";
            case "GCOVLimit":
                return "Нижний порог отображения GCOV";
            case "Precompilation":
                return "Предварительная компиляция";
            //------------------------------------------>>
            case "STATIC_SHADOW_ANALYSIS":
                return "Оптимизация теневых обменов";
            case "STATIC_PRIVATE_ANALYSIS":
                return "Статический анализ приватностей";
            case "FREE_FORM":
                return "Свободный выходной стиль";
            case "KEEP_DVM_DIRECTIVES":
                return "Учитывать DVM директивы";
            case "KEEP_SPF_DIRECTIVES":
                return "Сохранять SPF директивы при построении параллельных вариантов";
            case "PARALLELIZE_FREE_LOOPS":
                return "Улучшенное распараллеливание";
            case "MAX_SHADOW_WIDTH":
                return "Максимальный размер теневых граней";
            case "OUTPUT_UPPER":
                return "Верхний выходной регистр";
            case "TRANSLATE_MESSAGES":
                return "Сообщения на русском языке";
            case "KEEP_LOOPS_CLOSE_NESTING":
                return "Учитывать тесную вложенность циклов";
            case "KEEP_GCOV":
                return "Учитывать GCOV";
            case "ANALYSIS_OPTIONS":
                return "Опции анализа";
            case "DEBUG_PRINT_ON":
                return "Включить отладочную печать";
            case "MPI_PROGRAM":
                return "Общая память";
            case "IGNORE_IO_SAPFOR":
                return "Игнорировать ввод/вывод";
            case "KEEP_SPF_DIRECTIVES_AMONG_TRANSFORMATIONS":
                return "Сохранять SPF директивы при преобразованиях";
            case "PARSE_FOR_INLINE":
                return "Синтаксический анализ для подстановки";
            //------------------------------------------------------
        }
        return "";
    }
    //--
    @Override
    public boolean controlAction(String fieldName, JMenuItem control) {
        return (Global.mainModule.getPass(PassCode.UpdateSapforProperty).Do(fieldName));
    }
    public String getSummary() {
        Vector<String> res = new Vector<>();
        for (Field field : this.getClass().getFields()) {
            try {
                res.add(getFieldDescription(field.getName()) + "=" + field.get(this));
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        return String.join("\n", res);
    }
    //--
    public void applyProfile(Vector<SapforProfileSetting> settings) {
        Vector<String> changedFields = new Vector<>();
        try {
            for (SapforProfileSetting setting : settings) {
                Field field = null;
                try {
                    field = getClass().getField(setting.name);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
                if (field != null) {
                    if (field.getName().equals(setting.name)) {
                        changedFields.add(setting.name);
                        switch (setting.name) {
                            case "GCOVLimit":
                                GCOVLimit = Integer.parseInt(setting.value);
                                break;
                            case "MAX_SHADOW_WIDTH":
                                MAX_SHADOW_WIDTH = Integer.parseInt(setting.value);
                                break;
                            case "ANALYSIS_OPTIONS":
                                ANALYSIS_OPTIONS = setting.value;
                                break;
                            case "DVMConvertationOptions":
                                DVMConvertationOptions = setting.value;
                                break;
                            default:
                                int value_ = Integer.parseInt(setting.value);
                                field.set(this, value_ != 0);
                                break;
                        }
                    }
                }
            }
            if (!changedFields.isEmpty()) {
                this.Update();
                for (String fieldName : changedFields) {
                    Mark(fieldName, getMenuItem(fieldName));
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
    public void applyBugReportSettings(BugReport bugReport) {
        Vector<String> changedFields = new Vector<>();
        Vector<BugReportSetting> settings = Global.componentsServer.db.getVectorByFK(bugReport, BugReportSetting.class);
        for (BugReportSetting setting : settings) {
            try {
                Field field = null;
                try {
                    field = getClass().getField(setting.name);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
                if (field != null) {
                    if (field.getName().equals(setting.name)) {
                        changedFields.add(setting.name);
                        switch (setting.name) {
                            case "GCOVLimit":
                                GCOVLimit = Integer.parseInt(setting.value);
                                break;
                            case "MAX_SHADOW_WIDTH":
                                MAX_SHADOW_WIDTH = Integer.parseInt(setting.value);
                                break;
                            case "ANALYSIS_OPTIONS":
                                ANALYSIS_OPTIONS = setting.value;
                                break;
                            case "DVMConvertationOptions":
                                DVMConvertationOptions = setting.value;
                                break;
                            default:
                                int value_ = Integer.parseInt(setting.value);
                                field.set(this, value_ != 0);
                                break;
                        }
                    }
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
        if (!changedFields.isEmpty()) {
            this.Update();
            for (String fieldName : changedFields) {
                Mark(fieldName, getMenuItem(fieldName));
            }
        }
    }
    //--
    public LinkedHashMap<String, String> toMap() {
        LinkedHashMap<String, String> res = new LinkedHashMap<>();
        Vector<String> forbidden = new Vector_<String>(
                //     "Precompilation",
                //     "SaveModifications",
                //     "GCOVLimit",
                //     "DVMConvertationOptions",
                "PARSE_FOR_INLINE",
                "STATIC_PRIVATE_ANALYSIS",
                "PARALLELIZE_FREE_LOOPS"
        );
        try {
            for (Field field : getClass().getFields()) {
                if (!forbidden.contains(field.getName())) {
                    Object value = field.get(this);
                    String value_ = (value instanceof Boolean) ? ((boolean) value ? "1" : "0") : value.toString();
                    res.put(field.getName(), value_);
                }
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return res;
    }
    //--
    public Vector<BugReportSetting> toBugReportSettings() {
        Vector<BugReportSetting> res = new Vector<>();
        res.addAll(new Vector_<>(
                new BugReportSetting("STATIC_SHADOW_ANALYSIS", STATIC_SHADOW_ANALYSIS),
                new BugReportSetting("STATIC_PRIVATE_ANALYSIS", STATIC_PRIVATE_ANALYSIS),
                new BugReportSetting("FREE_FORM", FREE_FORM),
                new BugReportSetting("KEEP_DVM_DIRECTIVES", KEEP_DVM_DIRECTIVES),
                new BugReportSetting("KEEP_SPF_DIRECTIVES", KEEP_SPF_DIRECTIVES),
                new BugReportSetting("PARALLELIZE_FREE_LOOPS", PARALLELIZE_FREE_LOOPS),
                new BugReportSetting("MAX_SHADOW_WIDTH", MAX_SHADOW_WIDTH),
                new BugReportSetting("OUTPUT_UPPER", OUTPUT_UPPER),
                new BugReportSetting("TRANSLATE_MESSAGES", TRANSLATE_MESSAGES),
                new BugReportSetting("KEEP_LOOPS_CLOSE_NESTING", KEEP_LOOPS_CLOSE_NESTING),
                new BugReportSetting("KEEP_GCOV", KEEP_GCOV),
                new BugReportSetting("ANALYSIS_OPTIONS", ANALYSIS_OPTIONS),
                new BugReportSetting("DEBUG_PRINT_ON", DEBUG_PRINT_ON),
                new BugReportSetting("MPI_PROGRAM", MPI_PROGRAM),
                new BugReportSetting("IGNORE_IO_SAPFOR", IGNORE_IO_SAPFOR),
                new BugReportSetting("KEEP_SPF_DIRECTIVES_AMONG_TRANSFORMATIONS", KEEP_SPF_DIRECTIVES_AMONG_TRANSFORMATIONS),
                new BugReportSetting("PARSE_FOR_INLINE", PARSE_FOR_INLINE),
                new BugReportSetting("Precompilation", Precompilation),
                new BugReportSetting("SaveModifications", SaveModifications),
                new BugReportSetting("GCOVLimit", GCOVLimit),
                new BugReportSetting("DVMConvertationOptions", DVMConvertationOptions)
        ));
        return res;
    }
}
