package at.fos.ermodel.gui;

import javafx.scene.control.Tab;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.ArrayList;

public class ZZ30 {
    private final B3 view;
    private ArrayList<Graphic_Main_Elem> graphicElements;
    private C4 relationalModel;
    private Graphic_ES_Elem topES;

    public ZZ30(B3 view, ArrayList<Graphic_Main_Elem> graphicElements, C4 relationalModel) {
        this(view);
        this.graphicElements.addAll(graphicElements);
        this.relationalModel = relationalModel;
    }


    public ZZ30(B3 view) {
        this.view = view;
        this.graphicElements = new ArrayList<>();
    }


    public boolean lkshjdskjhsdlkjhds() {
        this.relationalModel.setTables(new ArrayList<>());


        ArrayList<Long> esTraversed = new ArrayList<>();


        for (Graphic_Main_Elem gme : this.graphicElements) {

            T1 table = null;
            String relationName;


            Graphic_ES_Main_Elem entitySet = null;
            if (gme instanceof Graphic_ES_Main_Elem) {
                entitySet = (Graphic_ES_Main_Elem) gme;

                if (entitySet.getCreateRelation()) {
                    relationName = entitySet.getRelationName();
                    if (entitySet.getRelationPraefix().length() > 0)
                        relationName = entitySet.getRelationPraefix() + entitySet.getRelationName();
                    table = new T1(relationName, entitySet.getRelationPraefix(), gme.sdfsdfsdfd(),
                            entitySet.getCreateInserts(), entitySet.getNumberRowsToInsert());

                    ArrayList<Graphic_Main_Elem> keyAttributes = getKeyAttributes(gme);
                    if (keyAttributes.size() > 1) {


                        this.view.verticalBox.getChildren().clear();
                        this.view.generateRelationalModelCB.setSelected(false);
                        return false;
                    }
                    ArrayList<Graphic_Main_Elem> weakkeyAttributes = getWeakKeyAttributes(gme);

                    if (!(gme instanceof Graphic_ES_Weak_Elem) && !(gme instanceof Graphic_ES_Assoc_Elem) && weakkeyAttributes.size() == 1) {


                        this.view.verticalBox.getChildren().clear();
                        this.view.generateRelationalModelCB.setSelected(false);
                        return false;
                    }

                    if (weakkeyAttributes.size() > 0 && keyAttributes.size() > 0) {


                        this.view.verticalBox.getChildren().clear();
                        this.view.generateRelationalModelCB.setSelected(false);
                        return false;
                    }


                    ArrayList<Graphic_Main_Elem> attributes = getAttributes(gme);
                    addColumnsToTable(table, attributes);
                }
            }
            if (table != null) {
                boolean tableAdded = false;
                while (!tableAdded) {
                    if (this.relationalModel.addTable(table)) {
                        entitySet.setRelationName(entitySet.getRelationName() + "_1");
                        relationName = entitySet.getRelationPraefix() + entitySet.getRelationName();
                        table.setTablename(relationName);
                        continue;
                    }
                    tableAdded = true;
                }
            }
        }


        ArrayList<Graphic_ES_Elem> topESets = new ArrayList<>();
        for (Graphic_Main_Elem gme : this.graphicElements) {


            if (gme instanceof Graphic_RS_ISA_Elem grsisae) {


                this.topES = null;
                try {
                    this.topES = getTopES(grsisae);
                    if (!esTraversed.contains(this.topES.sdfsdfsdfd())) {

                        esTraversed.add(this.topES.sdfsdfsdfd());

                        topESets.add(this.topES);
                    }
                } catch (StackOverflowError ignored) {
                }
            }
        }


        for (Graphic_ES_Elem gme : topESets) {
            traverseThroughISA(gme);
        }


        for (Graphic_Main_Elem gme : this.graphicElements) {
            T1 table = null;
            String relationName;


            Graphic_RS_Main_Elem relationshipType = null;
            if (gme instanceof Graphic_RS_Main_Elem) {
                relationshipType = (Graphic_RS_Main_Elem) gme;

                if (relationshipType.getCreateRelation()) {
                    relationName = relationshipType.getRelationName();
                    if (relationshipType.getRelationPraefix().length() > 0)
                        relationName = relationshipType.getRelationPraefix() + relationshipType.getRelationName();
                    table = new T1(relationName, relationshipType.getRelationPraefix(), gme.sdfsdfsdfd(),
                            relationshipType.getCreateInserts(), relationshipType.getNumberRowsToInsert());
                    ArrayList<Graphic_Main_Elem> attributes = getAttributes(gme);
                    addColumnsToTable(table, attributes);
                }
            }
            if (table != null) {
                boolean tableAdded = false;
                while (!tableAdded) {
                    if (this.relationalModel.addTable(table)) {


                        relationshipType.setRelationName(relationshipType.getRelationName() + "_1");
                        relationName = relationshipType.getRelationPraefix() + relationshipType.getRelationName();
                        table.setTablename(relationName);
                        continue;
                    }
                    tableAdded = true;
                }
            }
        }


        for (Graphic_Main_Elem gme : this.graphicElements) {
            T1 table = null;
            String relationName;


            Graphic_ATTR_Multi_Elem mvAttribute = null;
            if (gme instanceof Graphic_ATTR_Multi_Elem) {
                mvAttribute = (Graphic_ATTR_Multi_Elem) gme;
                relationName = mvAttribute.getMVRelationName();
                if (mvAttribute.getMVRelationNamePraefix().length() > 0)
                    relationName = mvAttribute.getMVRelationNamePraefix() + mvAttribute.getMVRelationName();

                table = new T1(relationName, mvAttribute.getMVRelationNamePraefix(), gme.sdfsdfsdfd(), false, 0L);
                C3 column = new C3(mvAttribute.getMVRelationNamePraefix() + mvAttribute.getColumnName() + ((
                        mvAttribute.getColumnPostfix() != null && mvAttribute.getColumnPostfix().length() > 0) ? mvAttribute.getColumnPostfix() : ""),
                        mvAttribute.getDatatype(),
                        true,
                        false,
                        false,
                        false,
                        mvAttribute.getAutoincrementStartAt(),
                        null,
                        table.getReferstoGraphicalElement(),
                        null, null, null);
                table.addColumn(column);

                Graphic_ES_Main_Elem gesme = getESGivenNumber(gme.sdfsdfsdfd());

                T1 tableForgemse = this.relationalModel.getTableGivenNumber(gesme.sdfsdfsdfd());
                ArrayList<C3> keyColumns = this.relationalModel.getKeyColumnsGivenRelation(gesme.sdfsdfsdfd());
                for (C3 refcolumn : keyColumns) {
                    column = new C3(mvAttribute.getMVRelationNamePraefix() + refcolumn.getColumnName(),
                            refcolumn.getDatatype(), false, false, false, false,
                            refcolumn.getAutoincrementStartAt(),
                            new T2(tableForgemse.getTablename(), refcolumn.getColumnName()),
                            gme.sdfsdfsdfd(),
                            null, null, null);
                    table.addColumn(column);
                }
            }
            if (table != null) {
                boolean tableAdded = false;
                while (!tableAdded) {
                    if (this.relationalModel.addTable(table)) {


                        mvAttribute.setMVRelationName(mvAttribute.getMVRelationName() + "_1");
                        relationName = mvAttribute.getMVRelationNamePraefix() + mvAttribute.getMVRelationName();
                        table.setTablename(relationName);
                        continue;
                    }
                    tableAdded = true;
                }
            }
        }


        for (Graphic_Main_Elem gme : this.graphicElements) {
            if (gme instanceof Graphic_ES_Assoc_Elem grsem) {

                ArrayList<Graphic_ES_Main_Elem> gesme = getConnectedESToAssociativeESGivenElemNumber(grsem.sdfsdfsdfd());


                boolean partPrimary = true;

                ArrayList<Graphic_Main_Elem> keys = getKeyAttributes(grsem);
                if (keys.size() > 0) partPrimary = false;
                keys = getWeakKeyAttributes(grsem);
                if (!partPrimary && keys.size() > 0) {


                    this.view.verticalBox.getChildren().clear();
                    this.view.generateRelationalModelCB.setSelected(false);
                    return false;
                }


                for (Graphic_ES_Main_Elem gesme_conn : gesme) {
                    T1 tableES = this.relationalModel.getTableGivenNumber(gesme_conn.sdfsdfsdfd());


                    ArrayList<C3> keyColumns = this.relationalModel.getKeyColumnsGivenRelation(gesme_conn.sdfsdfsdfd());

                    T1 tableRS = this.relationalModel.getTableGivenNumber(grsem.sdfsdfsdfd());
                    for (C3 refcolumn : keyColumns) {

                        boolean colExists = tableRS.columnExist(tableRS.getTablenamePraefix() + refcolumn.getColumnName());
                        C3 column = new C3(tableRS.getTablenamePraefix() + refcolumn.getColumnName() + (colExists ? "_1" : ""),
                                refcolumn.getDatatype(),
                                partPrimary,
                                false,
                                false,
                                false,
                                refcolumn.getAutoincrementStartAt(),
                                new T2(tableES.getTablename(), refcolumn.getColumnName()),
                                tableRS.getReferstoGraphicalElement(),

                                null,
                                null,
                                null);

                        tableRS.addColumn(column);
                    }
                }
            }
        }


        ArrayList<Graphic_Main_Elem> doneWeakElements = new ArrayList<>();
        for (Graphic_Main_Elem gme : this.graphicElements) {

            if (gme instanceof Graphic_RS_Main_Elem grsem) {


                if (grsem instanceof Graphic_RS_Identifying_Elem grsie) {

                    ArrayList<Graphic_ES_Main_Elem> connectedES = getConnectedESToRelationshipGivenElemNumber(grsie.sdfsdfsdfd());

                    if (connectedES.size() != 2) {


                        this.view.verticalBox.getChildren().clear();
                        this.view.generateRelationalModelCB.setSelected(false);
                        return false;
                    }

                    Graphic_ES_Main_Elem gw_es = null;
                    Graphic_ES_Main_Elem ges = null;


                    if (connectedES.get(0) instanceof Graphic_ES_Weak_Elem && connectedES.get(1) instanceof Graphic_ES_Weak_Elem) {
                        continue;
                    }

                    if (connectedES.get(0) instanceof Graphic_ES_Weak_Elem &&
                            connectedES.get(1) instanceof Graphic_ES_Elem) {
                        gw_es = connectedES.get(0);
                        ges = connectedES.get(1);
                    }
                    if (connectedES.get(1) instanceof Graphic_ES_Weak_Elem &&
                            connectedES.get(0) instanceof Graphic_ES_Elem) {
                        gw_es = connectedES.get(1);
                        ges = connectedES.get(0);
                    }

                    if (connectedES.get(0) instanceof Graphic_ES_Weak_Elem &&
                            connectedES.get(1) instanceof Graphic_ES_Assoc_Elem) {
                        gw_es = connectedES.get(0);
                        ges = connectedES.get(1);
                    }
                    if (connectedES.get(1) instanceof Graphic_ES_Weak_Elem &&
                            connectedES.get(0) instanceof Graphic_ES_Assoc_Elem) {
                        gw_es = connectedES.get(1);
                        ges = connectedES.get(0);
                    }


                    if (handleWeakElements(doneWeakElements, gw_es, ges)) return false;
                }
            }
        }


        int countNotTransformedWeakES = 0;
        for (Graphic_Main_Elem gme : this.graphicElements) {

            if (gme instanceof Graphic_RS_Main_Elem grsem) {


                if (grsem instanceof Graphic_RS_Identifying_Elem grsie) {

                    ArrayList<Graphic_ES_Main_Elem> connectedES = getConnectedESToRelationshipGivenElemNumber(grsie.sdfsdfsdfd());

                    if (connectedES.size() != 2) {


                        this.view.verticalBox.getChildren().clear();
                        this.view.generateRelationalModelCB.setSelected(false);
                        return false;
                    }


                    if (connectedES.get(0) instanceof Graphic_ES_Weak_Elem && connectedES.get(1) instanceof Graphic_ES_Weak_Elem) {
                        countNotTransformedWeakES++;
                    }
                }
            }
        }
        while (countNotTransformedWeakES > 0) {
            for (Graphic_Main_Elem gme : this.graphicElements) {

                if (gme instanceof Graphic_RS_Main_Elem grsem) {


                    if (grsem instanceof Graphic_RS_Identifying_Elem grsie) {

                        ArrayList<Graphic_ES_Main_Elem> connectedES = getConnectedESToRelationshipGivenElemNumber(grsie.sdfsdfsdfd());

                        if (connectedES.size() != 2) {


                            this.view.verticalBox.getChildren().clear();
                            this.view.generateRelationalModelCB.setSelected(false);
                            return false;
                        }

                        Graphic_ES_Weak_Elem gw_es = null;
                        Graphic_ES_Weak_Elem ges = null;


                        if (connectedES.get(0) instanceof Graphic_ES_Weak_Elem && connectedES.get(1) instanceof Graphic_ES_Weak_Elem) {
                            if (doneWeakElements.contains(connectedES.get(0))) {
                                ges = (Graphic_ES_Weak_Elem) connectedES.get(0);
                                gw_es = (Graphic_ES_Weak_Elem) connectedES.get(1);
                            } else if (doneWeakElements.contains(connectedES.get(1))) {
                                gw_es = (Graphic_ES_Weak_Elem) connectedES.get(0);
                                ges = (Graphic_ES_Weak_Elem) connectedES.get(1);
                            }


                            countNotTransformedWeakES--;

                            if (handleWeakElements(doneWeakElements, gw_es, ges)) return false;
                        }
                    }
                }
            }
        }


        for (Graphic_Main_Elem gme : this.graphicElements) {

            if (gme instanceof Graphic_RS_Main_Elem grsem) {


                if (grsem instanceof Graphic_RS_Elem) {

                    ArrayList<Graphic_ES_Main_Elem> gesme = getConnectedESToRelationshipGivenElemNumber(grsem.sdfsdfsdfd());


                    if (gesme.size() < 2) {


                        this.view.verticalBox.getChildren().clear();
                        this.view.generateRelationalModelCB.setSelected(false);
                        return false;
                    }


                    if (gesme.size() == 2) {


                        String[] minMax0;
                        String[] minMax1;

                        String max0;
                        String max1;
                        String min0;
                        String min1;


                        if (gesme.get(0).equals(gesme.get(1))) {
                            String[] minMaxRecursive = getMinMaxForGivenESRSIfRecursive(grsem.sdfsdfsdfd(), gesme.get(0).sdfsdfsdfd());
                            min0 = minMaxRecursive[0];
                            max0 = minMaxRecursive[1];
                            min1 = minMaxRecursive[2];
                            max1 = minMaxRecursive[3];
                        } else {

                            minMax0 = getMinMaxForGivenESRS(grsem.sdfsdfsdfd(), gesme.get(0).sdfsdfsdfd());
                            minMax1 = getMinMaxForGivenESRS(grsem.sdfsdfsdfd(), gesme.get(1).sdfsdfsdfd());
                            max0 = minMax0[1];
                            max1 = minMax1[1];
                            min0 = minMax0[0];
                            min1 = minMax1[0];
                        }


                        boolean manyToMany = !max0.equals("1") && !max1.equals("1");
                        boolean oneToMany = (max0.equals("1") && !max1.equals("1")) || (
                                !max0.equals("1") && max1.equals("1"));
                        boolean oneToOne = max0.equals("1") && max1.equals("1");


                        if (oneToOne) {

                            if (handleKey(grsem)) return false;


                            Graphic_ES_Main_Elem es_min_1_side;
                            Graphic_ES_Main_Elem es_min_0_side;
                            boolean bothSides_min_1 = false;
                            if (min0.equals("1") && min1.equals("0")) {
                                es_min_1_side = gesme.get(0);
                                es_min_0_side = gesme.get(1);
                            } else if (min1.equals("1") && min0.equals("0")) {
                                es_min_1_side = gesme.get(1);
                                es_min_0_side = gesme.get(0);
                            } else if (min1.equals("1") && min0.equals("1")) {
                                es_min_1_side = gesme.get(1);
                                es_min_0_side = gesme.get(0);
                                bothSides_min_1 = true;
                            } else {
                                es_min_1_side = gesme.get(0);
                                es_min_0_side = gesme.get(1);
                            }


                            T1 tableRS = this.relationalModel.getTableGivenNumber(grsem.sdfsdfsdfd());

                            addTableC3(es_min_1_side, es_min_0_side, tableRS);
                            if (bothSides_min_1) {
                                addTableC3(es_min_0_side, es_min_1_side, tableRS);
                            }


                            this.relationalModel.removeTable(tableRS);
                        }


                        if (oneToMany) {

                            if (handleKey(grsem)) return false;


                            T1 tableRS = this.relationalModel.getTableGivenNumber(grsem.sdfsdfsdfd());
                            Graphic_ES_Main_Elem es_n_side;
                            Graphic_ES_Main_Elem es_1_side;
                            if (max0.equals("1")) {
                                es_n_side = gesme.get(1);
                                es_1_side = gesme.get(0);
                            } else {
                                es_n_side = gesme.get(0);
                                es_1_side = gesme.get(1);
                            }

                            T1 tableES = this.relationalModel.getTableGivenNumber(es_n_side.sdfsdfsdfd());
                            ArrayList<C3> keyColumns = this.relationalModel.getKeyColumnsGivenRelation(es_n_side.sdfsdfsdfd());
                            T1 table_1_side = this.relationalModel.getTableGivenNumber(es_1_side.sdfsdfsdfd());
                            for (C3 refcolumn : keyColumns) {

                                C3 column = new C3(table_1_side.getTablenamePraefix() + ((
                                        tableRS != null && tableRS.getTablename().length() > 0) ? (tableRS.getTablename() + "_") : "") +
                                        refcolumn.getColumnName(),
                                        refcolumn.getDatatype(),
                                        false,
                                        true,
                                        false,
                                        false,
                                        refcolumn.getAutoincrementStartAt(),
                                        new T2(tableES.getTablename(), refcolumn.getColumnName()),
                                        table_1_side.getReferstoGraphicalElement(),

                                        null,
                                        null,
                                        null);
                                table_1_side.addColumn(column);
                            }


                            this.relationalModel.removeTable(tableRS);
                        }


                        if (manyToMany) {


                            boolean partPrimary = true;

                            ArrayList<Graphic_Main_Elem> keys = getKeyAttributes(grsem);
                            if (keys.size() > 0) partPrimary = false;
                            keys = getWeakKeyAttributes(grsem);
                            if (!partPrimary && keys.size() > 0) {


                                this.view.verticalBox.getChildren().clear();
                                this.view.generateRelationalModelCB.setSelected(false);
                                return false;
                            }


                            boolean recursiveRelationship = (gesme.get(0).sdfsdfsdfd() == gesme.get(1).sdfsdfsdfd());
                            T1 tableES = this.relationalModel.getTableGivenNumber(gesme.get(0).sdfsdfsdfd());
                            ArrayList<C3> keyColumns = this.relationalModel.getKeyColumnsGivenRelation(gesme.get(0).sdfsdfsdfd());
                            T1 tableRS = this.relationalModel.getTableGivenNumber(grsem.sdfsdfsdfd());
                            for (C3 refcolumn : keyColumns) {

                                C3 column = new C3(tableRS.getTablenamePraefix() + refcolumn.getColumnName() + (recursiveRelationship ? "_1" : ""),
                                        refcolumn.getDatatype(),
                                        partPrimary,
                                        !partPrimary,
                                        false,
                                        false,
                                        refcolumn.getAutoincrementStartAt(),
                                        new T2(tableES.getTablename(), refcolumn.getColumnName()),
                                        tableRS.getReferstoGraphicalElement(),

                                        null,
                                        null,
                                        null);
                                tableRS.addColumn(column);
                            }

                            tableES = this.relationalModel.getTableGivenNumber(gesme.get(1).sdfsdfsdfd());
                            keyColumns = this.relationalModel.getKeyColumnsGivenRelation(gesme.get(1).sdfsdfsdfd());
                            tableRS = this.relationalModel.getTableGivenNumber(grsem.sdfsdfsdfd());
                            for (C3 refcolumn : keyColumns) {

                                C3 column = new C3(tableRS.getTablenamePraefix() + refcolumn.getColumnName() + (recursiveRelationship ? "_2" : ""),
                                        refcolumn.getDatatype(),
                                        partPrimary,
                                        !partPrimary,
                                        false,
                                        false,
                                        refcolumn.getAutoincrementStartAt(),
                                        new T2(tableES.getTablename(), refcolumn.getColumnName()),
                                        tableRS.getReferstoGraphicalElement(),

                                        null,
                                        null,
                                        null);
                                tableRS.addColumn(column);
                            }
                        }
                    }


                    if (gesme.size() > 2) {

                        boolean partPrimary = true;

                        ArrayList<Graphic_Main_Elem> keys = getKeyAttributes(grsem);
                        if (keys.size() > 0) partPrimary = false;
                        keys = getWeakKeyAttributes(grsem);
                        if (!partPrimary && keys.size() > 0) {


                            this.view.verticalBox.getChildren().clear();
                            this.view.generateRelationalModelCB.setSelected(false);
                            return false;
                        }


                        for (Graphic_ES_Main_Elem gesme_conn : gesme) {
                            T1 tableES = this.relationalModel.getTableGivenNumber(gesme_conn.sdfsdfsdfd());

                            ArrayList<C3> keyColumns = this.relationalModel.getKeyColumnsGivenRelation(gesme_conn.sdfsdfsdfd());

                            T1 tableRS = this.relationalModel.getTableGivenNumber(grsem.sdfsdfsdfd());

                            String[] minMax = getMinMaxForGivenESRS(grsem.sdfsdfsdfd(), gesme_conn.sdfsdfsdfd());
                            for (C3 refcolumn : keyColumns) {

                                boolean colExists = tableRS.columnExist(tableRS.getTablenamePraefix() + refcolumn.getColumnName());

                                C3 column = new C3(tableRS.getTablenamePraefix() + refcolumn.getColumnName() + (colExists ? "_1" : ""),
                                        refcolumn.getDatatype(),
                                        partPrimary,
                                        !partPrimary,
                                        minMax[1].equals("1"),
                                        false,
                                        refcolumn.getAutoincrementStartAt(),
                                        new T2(tableES.getTablename(), refcolumn.getColumnName()),
                                        tableRS.getReferstoGraphicalElement(),

                                        null,
                                        null,
                                        null);

                                tableRS.addColumn(column);
                            }
                        }
                    }
                }
            }
        }


        this.relationalModel.sortByTableName();

        return true;
    }

    private boolean handleWeakElements(ArrayList<Graphic_Main_Elem> doneWeakElements, Graphic_ES_Main_Elem gw_es, Graphic_ES_Main_Elem ges) {
        doneWeakElements.add(gw_es);


        boolean partPrimary = true;

        ArrayList<Graphic_Main_Elem> keys = getKeyAttributes(gw_es);
        if (keys.size() > 0) partPrimary = false;
        keys = getWeakKeyAttributes(gw_es);
        if (!partPrimary && keys.size() > 0) {


            this.view.verticalBox.getChildren().clear();
            this.view.generateRelationalModelCB.setSelected(false);
            return true;
        }


        assert ges != null;
        T1 tableForges = this.relationalModel.getTableGivenNumber(ges.sdfsdfsdfd());
        ArrayList<C3> keyColumns = this.relationalModel.getKeyColumnsGivenRelation(ges.sdfsdfsdfd());
        T1 tableForgwes = this.relationalModel.getTableGivenNumber(gw_es.sdfsdfsdfd());
        for (C3 refcolumn : keyColumns) {
            C3 column = new C3(tableForgwes.getTablenamePraefix() + refcolumn.getColumnName(),
                    refcolumn.getDatatype(),
                    partPrimary,
                    !partPrimary,
                    false,
                    false,
                    refcolumn.getAutoincrementStartAt(),
                    new T2(tableForges.getTablename(), refcolumn.getColumnName()),
                    tableForgwes.getReferstoGraphicalElement(),

                    null,
                    null,
                    null);
            tableForgwes.addColumn(column);
        }
        return false;
    }

    private boolean handleKey(Graphic_RS_Main_Elem grsem) {
        boolean keyCorrect = true;
        ArrayList<Graphic_Main_Elem> keys = getKeyAttributes(grsem);
        if (keys.size() > 0) keyCorrect = false;
        if (keyCorrect) {
            keys = getWeakKeyAttributes(grsem);
            if (keys.size() > 0) keyCorrect = false;

        }
        if (!keyCorrect) {


            this.view.verticalBox.getChildren().clear();
            this.view.generateRelationalModelCB.setSelected(false);
            return true;
        }
        return false;
    }

    private void addTableC3(Graphic_ES_Main_Elem es_min_1_side, Graphic_ES_Main_Elem es_min_0_side, T1 tableRS) {
        T1 tableES = this.relationalModel.getTableGivenNumber(es_min_0_side.sdfsdfsdfd());
        ArrayList<C3> keyColumns = this.relationalModel.getKeyColumnsGivenRelation(es_min_0_side.sdfsdfsdfd());
        T1 table_1_side = this.relationalModel.getTableGivenNumber(es_min_1_side.sdfsdfsdfd());

        for (C3 refcolumn : keyColumns) {
            C3 column = new C3(table_1_side.getTablenamePraefix() + (
                    (tableRS.getTablename().length() > 0) ? (tableRS.getTablename() + "_") : "") +
                    refcolumn.getColumnName(),
                    refcolumn.getDatatype(),
                    false,
                    true,
                    true,
                    false,
                    refcolumn.getAutoincrementStartAt(),
                    new T2(tableES.getTablename(), refcolumn.getColumnName()),
                    table_1_side.getReferstoGraphicalElement(),

                    null,
                    null,
                    null);
            table_1_side.addColumn(column);
        }
    }


    private ArrayList<Graphic_Main_Elem> getAttributes(Graphic_Main_Elem gme) {
        ArrayList<Graphic_Main_Elem> attributes = new ArrayList<>();
        for (Graphic_Main_Elem gmLooking : this.graphicElements) {


            if (gmLooking instanceof Graphic_LINE_Elem) {


                if (((Graphic_LINE_Elem) gmLooking).getConnectedWithEnd().sdfsdfsdfd() == gme.sdfsdfsdfd() && (
                        (Graphic_LINE_Elem) gmLooking).getConnectedWithStart() instanceof Graphic_ATTR_Elem gae) {

                    if (gae.getCreateColumn()) {
                        attributes.add(gae);
                    } else {
                        attributes.addAll(getAttributes(gae));
                    }

                }

                if (((Graphic_LINE_Elem) gmLooking).getConnectedWithStart().sdfsdfsdfd() == gme.sdfsdfsdfd() && (
                        (Graphic_LINE_Elem) gmLooking).getConnectedWithEnd() instanceof Graphic_ATTR_Elem gae) {

                    if (gae.getCreateColumn()) {
                        attributes.add(gae);

                        continue;
                    }

                    attributes.addAll(getAttributes(gae));
                }
            }
        }

        return attributes;
    }


    private void addColumnsToTable(T1 table, ArrayList<Graphic_Main_Elem> attributes) {
        for (Graphic_Main_Elem gme : attributes) {
            Graphic_ATTR_Elem gae = (Graphic_ATTR_Elem) gme;
            C3 column = new C3(table.getTablenamePraefix() +
                    gae.getColumnName() + ((
                    gae.getColumnPostfix() != null && gae.getColumnPostfix().length() > 0) ? gae.getColumnPostfix() : ""),
                    gae.getDatatype(),
                    gae.isKey(),
                    gae.isNullable(),
                    gae.isUnique(),
                    gae.isAutoincrement(),
                    gae.getAutoincrementStartAt(),
                    null,
                    table.getReferstoGraphicalElement(),
                    gae.getDataGenerationType(),
                    gae.getPar1(),
                    gae.getPar2());
            table.addColumn(column);
        }
    }


    private Graphic_ES_Elem getTopES(Graphic_RS_ISA_Elem grsisae) {
        for (Graphic_Main_Elem gme : this.graphicElements) {

            if (gme instanceof Graphic_LINE_RSISAG_ES_Elem) {
                if (((Graphic_LINE_RSISAG_ES_Elem) gme).getConnectedWithStart().sdfsdfsdfd() == grsisae.sdfsdfsdfd()) {
                    this.topES = (Graphic_ES_Elem) ((Graphic_LINE_RSISAG_ES_Elem) gme).getConnectedWithEnd();
                }

                if (((Graphic_LINE_RSISAG_ES_Elem) gme).getConnectedWithEnd().sdfsdfsdfd() == grsisae.sdfsdfsdfd()) {
                    this.topES = (Graphic_ES_Elem) ((Graphic_LINE_RSISAG_ES_Elem) gme).getConnectedWithStart();
                }
            }
        }


        for (Graphic_Main_Elem gme : this.graphicElements) {
            if (gme instanceof Graphic_LINE_RSISAS_ES_Elem) {
                if (((Graphic_LINE_RSISAS_ES_Elem) gme).getConnectedWithStart().sdfsdfsdfd() == this.topES.sdfsdfsdfd()) {
                    getTopES((Graphic_RS_ISA_Elem) ((Graphic_LINE_RSISAS_ES_Elem) gme).getConnectedWithEnd());
                }
                if (((Graphic_LINE_RSISAS_ES_Elem) gme).getConnectedWithEnd().sdfsdfsdfd() == this.topES.sdfsdfsdfd()) {
                    getTopES((Graphic_RS_ISA_Elem) ((Graphic_LINE_RSISAS_ES_Elem) gme).getConnectedWithStart());
                }
            }
        }

        return this.topES;
    }


    private void traverseThroughISA(Graphic_ES_Elem topES) {
        Graphic_RS_ISA_Elem topESConnectedWithISA = getISAOfTop(topES);

        if (topESConnectedWithISA == null)
            return;
        ArrayList<Graphic_ES_Elem> specializationsOfTopES;
        specializationsOfTopES = getSpecializationsOfTopES(topESConnectedWithISA);
        if (specializationsOfTopES.size() == 0) {
            return;
        }


        for (Graphic_ES_Elem specialization : specializationsOfTopES) {
            boolean partPrimary = true;
            ArrayList<Graphic_Main_Elem> keys = getKeyAttributes(specialization);
            if (keys.size() > 0) partPrimary = false;

            ArrayList<Graphic_Main_Elem> weakKeys = getWeakKeyAttributes(specialization);

            if (weakKeys.size() == 1) {
                return;
            }


            if (weakKeys.size() > 1) partPrimary = false;

            T1 tableES = this.relationalModel.getTableGivenNumber(topES.sdfsdfsdfd());
            ArrayList<C3> keyColumns = this.relationalModel.getKeyColumnsGivenRelation(topES.sdfsdfsdfd());
            T1 tableRS = this.relationalModel.getTableGivenNumber(specialization.sdfsdfsdfd());
            for (C3 refcolumn : keyColumns) {

                Graphic_ATTR_Elem gattre = getAttrElemGivenColumnName(tableRS.getTablenamePraefix() + refcolumn.getColumnName());

                C3 column = new C3(tableRS.getTablenamePraefix() + refcolumn.getColumnName(),
                        refcolumn.getDatatype(),
                        partPrimary,
                        false,
                        !partPrimary,
                        false,
                        refcolumn.getAutoincrementStartAt(),
                        new T2(tableES.getTablename(), refcolumn.getColumnName()),
                        tableRS.getReferstoGraphicalElement(),

                        gattre.getDataGenerationType(),
                        gattre.getPar1(),
                        gattre.getPar2());
                tableRS.addColumn(column);
            }

            traverseThroughISA(specialization);
        }
    }


    public Graphic_ES_Main_Elem getESGivenNumber(long elementNr) {

        for (Graphic_Main_Elem gme : this.graphicElements) {

            if (gme instanceof Graphic_LINE_Attr_ES_Elem glaese) {
                if (glaese.getConnectedWithEnd().sdfsdfsdfd() == elementNr)
                    return (Graphic_ES_Main_Elem) glaese.getConnectedWithStart();
                if (glaese.getConnectedWithStart().sdfsdfsdfd() == elementNr)
                    return (Graphic_ES_Main_Elem) glaese.getConnectedWithEnd();
            }
        }
        return null;
    }


    private ArrayList<Graphic_ES_Main_Elem> getConnectedESToRelationshipGivenElemNumber(long elementNr) {
        ArrayList<Graphic_ES_Main_Elem> connections = new ArrayList<>();
        for (Graphic_Main_Elem gme : this.graphicElements) {
            if (gme instanceof Graphic_LINE_Attr_Attr_Elem || gme instanceof Graphic_LINE_Attr_ES_Elem || gme instanceof Graphic_LINE_Attr_RS_Elem)
                continue;
            if (gme instanceof Graphic_LINE_Elem gle) {
                if (gle.getConnectedWithEnd().sdfsdfsdfd() == elementNr)
                    connections.add((Graphic_ES_Main_Elem) gle.getConnectedWithStart());
                if (gle.getConnectedWithStart().sdfsdfsdfd() == elementNr)
                    connections.add((Graphic_ES_Main_Elem) gle.getConnectedWithEnd());
            }
        }
        return connections;
    }


    private ArrayList<Graphic_Main_Elem> getWeakKeyAttributes(Graphic_Main_Elem gme) {
        ArrayList<Graphic_Main_Elem> attributes = new ArrayList<>();
        for (Graphic_Main_Elem gmLooking : this.graphicElements) {


            if (gmLooking instanceof Graphic_LINE_Elem) {


                if (((Graphic_LINE_Elem) gmLooking).getConnectedWithEnd().sdfsdfsdfd() == gme.sdfsdfsdfd() && (
                        (Graphic_LINE_Elem) gmLooking).getConnectedWithStart() instanceof Graphic_ATTR_Weak_Key_Elem) {
                    Graphic_ATTR_Elem gae = (Graphic_ATTR_Elem) ((Graphic_LINE_Elem) gmLooking).getConnectedWithStart();

                    if (gae.getCreateColumn()) attributes.add(gae);
                }
                if (((Graphic_LINE_Elem) gmLooking).getConnectedWithStart().sdfsdfsdfd() == gme.sdfsdfsdfd() && (
                        (Graphic_LINE_Elem) gmLooking).getConnectedWithEnd() instanceof Graphic_ATTR_Weak_Key_Elem) {
                    Graphic_ATTR_Elem gae = (Graphic_ATTR_Elem) ((Graphic_LINE_Elem) gmLooking).getConnectedWithEnd();

                    if (gae.getCreateColumn()) attributes.add(gae);
                }
            }
        }
        return attributes;
    }


    private ArrayList<Graphic_Main_Elem> getKeyAttributes(Graphic_Main_Elem gme) {
        ArrayList<Graphic_Main_Elem> attributes = new ArrayList<>();
        for (Graphic_Main_Elem gmLooking : this.graphicElements) {


            if (gmLooking instanceof Graphic_LINE_Elem) {


                if (((Graphic_LINE_Elem) gmLooking).getConnectedWithEnd().sdfsdfsdfd() == gme.sdfsdfsdfd() && (
                        (Graphic_LINE_Elem) gmLooking).getConnectedWithStart() instanceof Graphic_ATTR_Key_Elem) {
                    Graphic_ATTR_Elem gae = (Graphic_ATTR_Elem) ((Graphic_LINE_Elem) gmLooking).getConnectedWithStart();

                    if (gae.getCreateColumn()) attributes.add(gae);
                }
                if (((Graphic_LINE_Elem) gmLooking).getConnectedWithStart().sdfsdfsdfd() == gme.sdfsdfsdfd() && (
                        (Graphic_LINE_Elem) gmLooking).getConnectedWithEnd() instanceof Graphic_ATTR_Key_Elem) {
                    Graphic_ATTR_Elem gae = (Graphic_ATTR_Elem) ((Graphic_LINE_Elem) gmLooking).getConnectedWithEnd();

                    if (gae.getCreateColumn()) attributes.add(gae);
                }
            }
        }
        return attributes;
    }


    private ArrayList<Graphic_ES_Main_Elem> getConnectedESToAssociativeESGivenElemNumber(long elementNr) {
        ArrayList<Graphic_ES_Main_Elem> connections = new ArrayList<>();
        for (Graphic_Main_Elem gme : this.graphicElements) {
            if (gme instanceof Graphic_LINE_Attr_Attr_Elem || gme instanceof Graphic_LINE_Attr_ES_Elem || gme instanceof Graphic_LINE_Attr_RS_Elem)
                continue;
            if (gme instanceof Graphic_LINE_Elem gle) {
                if (gle.getConnectedWithEnd().sdfsdfsdfd() == elementNr &&
                        gle.getConnectedWithStart() instanceof Graphic_ES_Main_Elem) {
                    connections.add((Graphic_ES_Main_Elem) gle.getConnectedWithStart());
                }
                if (gle.getConnectedWithStart().sdfsdfsdfd() == elementNr &&
                        gle.getConnectedWithEnd() instanceof Graphic_ES_Main_Elem) {
                    connections.add((Graphic_ES_Main_Elem) gle.getConnectedWithEnd());
                }
            }
        }
        return connections;
    }


    private String[] getMinMaxForGivenESRSIfRecursive(long rs, long es) {
        String[] minMax = new String[100];
        int counter = 0;
        for (Graphic_Main_Elem gme : this.graphicElements) {
            if (gme instanceof Graphic_LINE_RS_ES_Elem glrsese) {

                if ((glrsese.getConnectedWithEnd().sdfsdfsdfd() == rs && glrsese.getConnectedWithStart().sdfsdfsdfd() == es) || (
                        glrsese.getConnectedWithStart().sdfsdfsdfd() == rs && glrsese.getConnectedWithEnd().sdfsdfsdfd() == es)) {
                    minMax[counter++] = glrsese.getMinimum();
                    minMax[counter++] = glrsese.getMaximum();
                }
            }
        }
        return minMax;
    }


    private String[] getMinMaxForGivenESRS(long rs, long es) {
        String[] minMax = null;
        for (Graphic_Main_Elem gme : this.graphicElements) {
            if (gme instanceof Graphic_LINE_RS_ES_Elem glrsese) {

                if ((glrsese.getConnectedWithEnd().sdfsdfsdfd() == rs && glrsese.getConnectedWithStart().sdfsdfsdfd() == es) || (
                        glrsese.getConnectedWithStart().sdfsdfsdfd() == rs && glrsese.getConnectedWithEnd().sdfsdfsdfd() == es)) {
                    minMax = new String[2];
                    minMax[0] = glrsese.getMinimum();
                    minMax[1] = glrsese.getMaximum();
                }
            }
        }
        return minMax;
    }


    private Graphic_RS_ISA_Elem getISAOfTop(Graphic_ES_Elem topES) {
        for (Graphic_Main_Elem gme : this.graphicElements) {
            if (gme instanceof Graphic_LINE_RSISAG_ES_Elem) {
                if (((Graphic_LINE_RSISAG_ES_Elem) gme).getConnectedWithEnd().sdfsdfsdfd() == topES.sdfsdfsdfd()) {
                    return (Graphic_RS_ISA_Elem) ((Graphic_LINE_RSISAG_ES_Elem) gme).getConnectedWithStart();
                }
                if (((Graphic_LINE_RSISAG_ES_Elem) gme).getConnectedWithStart().sdfsdfsdfd() == topES.sdfsdfsdfd()) {
                    return (Graphic_RS_ISA_Elem) ((Graphic_LINE_RSISAG_ES_Elem) gme).getConnectedWithEnd();
                }
            }
        }
        return null;
    }


    private ArrayList<Graphic_ES_Elem> getSpecializationsOfTopES(Graphic_RS_ISA_Elem topESISA) {
        ArrayList<Graphic_ES_Elem> connectedES = new ArrayList<>();
        for (Graphic_Main_Elem gme : this.graphicElements) {
            if (gme instanceof Graphic_LINE_RSISAS_ES_Elem connectionToSpecialization) {
                if (connectionToSpecialization.getConnectedWithEnd().sdfsdfsdfd() == topESISA.sdfsdfsdfd()) {
                    connectedES.add((Graphic_ES_Elem) connectionToSpecialization.getConnectedWithStart());
                }
                if (connectionToSpecialization.getConnectedWithStart().sdfsdfsdfd() == topESISA.sdfsdfsdfd()) {
                    connectedES.add((Graphic_ES_Elem) connectionToSpecialization.getConnectedWithEnd());
                }
            }
        }
        return connectedES;
    }


    private Graphic_ATTR_Elem getAttrElemGivenColumnName(String columnName) {
        Graphic_ATTR_Elem gattre = null;
        for (Graphic_Main_Elem gme : this.graphicElements) {
            if (gme instanceof Graphic_ATTR_Elem) {
                gattre = (Graphic_ATTR_Elem) gme;
                if (gattre.getColumnName().equals(columnName)) return gattre;
            }
        }
        return gattre;
    }


    public C4 getRelationalModel() {
        return this.relationalModel;
    }


    public boolean mergeAllModelsInPanes() throws IOException, ClassNotFoundException {
        ArrayList<Graphic_Main_Elem> graphicElements = new ArrayList<>();

        for (Tab tab : this.view.tabPane.getTabs()) {
            U1 currentTab = (U1) tab;
            A3 canvas = currentTab.canvas;


            if (canvas.sddsfsfsdf45645645().size() == 0 || canvas.getSaveFile() == null)
                continue;
            ObjectInputStream ro = new ObjectInputStream(new FileInputStream(canvas.getSaveFile()));
            @SuppressWarnings("unchecked") ArrayList<Graphic_Main_Elem> readModel = (ArrayList<Graphic_Main_Elem>) ro.readObject();


            for (Graphic_Main_Elem gme : readModel) {

                if (gme instanceof Graphic_ES_Main_Elem) {


                    boolean elementExists = false;
                    for (Graphic_Main_Elem gmemergeto : graphicElements) {

                        if (gmemergeto instanceof Graphic_ES_Main_Elem &&
                                gmemergeto.sdfsdfsd32234243().equals(gme.sdfsdfsd32234243())) {
                            elementExists = true;


                            for (Graphic_Main_Elem line : readModel) {
                                if (line instanceof Graphic_LINE_Elem) {
                                    if (((Graphic_LINE_Elem) line).getConnectedWithEnd() == gme) {
                                        ((Graphic_LINE_Elem) line).setConnectedWithEnd((Graphic_Figure_Elem) gmemergeto);

                                        double[] getxy = ((Graphic_ES_Main_Elem) gmemergeto).getXYForGivenPoint(((Graphic_LINE_Elem) line).getLineConnectedWithPointAtEnd());
                                        ((Graphic_LINE_Elem) line).setxEnd(getxy[0]);
                                        ((Graphic_LINE_Elem) line).setyEnd(getxy[1]);
                                    }

                                    if (((Graphic_LINE_Elem) line).getConnectedWithStart() == gme) {
                                        ((Graphic_LINE_Elem) line).setConnectedWithStart((Graphic_Figure_Elem) gmemergeto);

                                        double[] getxy = ((Graphic_ES_Main_Elem) gmemergeto).getXYForGivenPoint(((Graphic_LINE_Elem) line).getLineConnectedWithPointAtStart());
                                        line.setxPos(getxy[0]);
                                        line.setyPos(getxy[1]);
                                    }
                                }
                            }
                        }
                    }


                    if (!elementExists) graphicElements.add(gme);
                    continue;
                }
                graphicElements.add(gme);
            }


            ro.close();
        }


        long elementId = 1L;
        for (Graphic_Main_Elem gme : graphicElements) {
            gme.dsdasadsasd32423432(elementId++);
        }
        this.graphicElements = graphicElements;
        return graphicElements.size() > 0;
    }


    public ArrayList<Graphic_Main_Elem> getGraphicElements() {
        return this.graphicElements;
    }
}


