package Common;
import Common.Database.Objects.PassStats.PassStats;
import Common.Database.VisualiserDatabase;
import Common.Passes.Pass;
import Common.Passes.PassCode_;
import Common.Utils.TextLog;
import Common.Visual.UIModule_;

import javax.swing.*;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.Vector;
//Основной объект визуализатора.
public abstract class MainModule_<D extends VisualiserDatabase, U extends UIModule_> {
    public static MainModule_ instance = null; //текущий экземпляр. всегда один.
    //--
    D db = null;
    Class<D> db_class = null;
    LinkedHashMap<Current_, Object> objects = null;  //Current/ большинство выведено
    //--
    LinkedHashMap<PassCode_, Pass> passes = null;
    //--
    U ui = null;
    Class<U> ui_class = null;
    MenuElement[] last_menu_path = null;
    //--
    public MainModule_(Class<D> db_class_in, Class<U> ui_class_in) throws Exception {
        ui_class = ui_class_in;
        db_class = db_class_in;
        instance = this;
    }
    public void Init() throws Exception {
        //нужно потому что внутри есть  ссылки на экземпляр объекта, и конструктор не годится
        if (ui_class != null) {
            ui = ui_class.newInstance();
        }
        //--
        createPasses();
        //-
        objects = new LinkedHashMap<>();
    }
    //ИНТЕРФЕЙС
    public boolean hasUI() {
        return ui != null;
    }
    public U getUI() {
        return ui;
    }
    public boolean hasLastMenuPath() {
        return last_menu_path != null;
    }
    public MenuElement[] getLastMenuPath() {
        return last_menu_path;
    }
    public MenuElement[] setLastMenuPath(MenuElement[] last_menu_path_in) {
        return last_menu_path = last_menu_path_in;
    }
    //БАЗА ДАННЫХ И ТЕКУЩИЕ ОБЪЕКТЫ
    public D getDb() {
        return db;
    }
    public void ActivateDB() throws Exception {
        db = db_class.newInstance();
        db.Connect();
        db.CreateAllTables();
        db.prepareTablesStatements();
        db.Synchronize();
    }
    public void DeactivateDB() throws Exception {
        if (db != null) db.Disconnect();
    }
    public Object get(Current_ name) {
        if (!objects.containsKey(name))
            objects.put(name, null);
        return objects.get(name);
    }
    public Object set(Current_ name, Object object) {
        if (objects.containsKey(name))
            objects.replace(name, object);
        else objects.put(name, object);
        return object;
    }
    public boolean Check(TextLog Log, Current_... names) {
        for (Current_ name : names)
            if (get(name) == null)
                Log.Writeln_(name.getDescription() + " не выбран(а)");
        return Log.isEmpty();
    }
    //ПРОХОДЫ
    public abstract Class getPassCodesEnum();
    public abstract String getAllPassesClassPrefix();
    private void createPasses() {
        passes = new LinkedHashMap<>();
        for (Object code : getPassCodesEnum().getEnumConstants()) {
            try {
                Class<?> clazz = Class.forName(getAllPassesClassPrefix() + code.toString());
                Pass pass = ((Pass) clazz.newInstance());
                passes.put((PassCode_) code, pass);
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        }
    }
    public void setPassesControlsVisible(boolean flag, PassCode_... codes_in) {
        for (PassCode_ code_in : codes_in)
            getPass(code_in).setControlsVisible(flag);
    }
    public Pass getPass(PassCode_ code) {
        return passes.get(code);
    }
    public String getPassDescription(String passName) {
        return ((PassCode_) Enum.valueOf(MainModule_.instance.getPassCodesEnum(), passName)).getDescription();
    }
    public Vector<Pass> getFirstAccessPasses() {
        Vector<PassStats> sortedStats = new Vector<>(getDb().passStats.Data.values());
        sortedStats.sort(new Comparator<PassStats>() {
            @Override
            public int compare(PassStats o1, PassStats o2) {
                return Integer.compare(o2.Usages, o1.Usages);
            }
        });
        Vector<Pass> res = new Vector<>();
        for (PassStats passStats : sortedStats) {
            PassCode_ passCode = (PassCode_) Enum.valueOf(getPassCodesEnum(), passStats.code);
            //--
            Pass pass = getPass(passCode);
            if (pass.hasStats())
                res.add(getPass(passCode));
            //--
        }
        return res;
    }
    //---
    public int getFirstAccessPassesCount() {
        return 0;
    }
    public boolean confirmPassesStart() {
        return false;
    }
    public boolean confirmPassesDone() {
        return false;
    }
    public boolean focusPassesResult() {
        return false;
    }
}
