package ui.view;

import classes.*;
import com.google.gson.JsonParseException;
import ui.controller.Control;
import ui.controller.UpdateController;
import ui.model.Model;

import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Line2D;
import java.io.IOException;
import java.util.ArrayList;

/**
 * This Class is the Canvas. All Objects will be visualized here
 *
 * @author Gruppe14
 */
public class MyCanvas extends AbstractCanvas implements MouseListener, MouseMotionListener {

    private static final long serialVersionUID = 1L;


    /**
     * Constructor.
     *
     * @param mod       the Model
     * @param control   the Controller
     * @param unitGraph
     */
    public MyCanvas(Model mod, Control control, UnitGraph unitGraph) {
        toolTip = false;
        this.controller = control;
        this.model = mod;
        scalediv20 = model.getScale() / 20;

        showedInformation[0] = true;
        showedInformation[1] = true;
        showedInformation[3] = false;
        showedInformation[4] = true;
        control.setMaxCapacity(10000);

        popmenu.add(itemCut);
        popmenu.add(itemCopy);
        popmenu.add(itemPaste);
        popmenu.add(itemDelete);
        popmenu.addSeparator();
        popmenu.add(itemGroup);
        popmenu.add(itemUngroup);
        popmenu.add(itemTrack);
        popmenu.add(itemUntrack);

        updCon = new UpdateController(mod, control);

        itemDelete.setEnabled(false);
        itemCut.setEnabled(false);
        itemCopy.setEnabled(false);
        itemPaste.setEnabled(true);
        itemGroup.setEnabled(false);
        itemUngroup.setEnabled(false);
        itemTrack.setEnabled(false);
        itemUntrack.setEnabled(false);

        itemCut.setText(Languages.getLanguage()[95]);

        itemGroup.addActionListener(actionEvent -> {
            // calculate uppernode pos (taken from the controller)
            unPos = new Position(0, 0);
            animCps = new ArrayList<>();
            for (AbstractCpsObject cps : model.getSelectedCpsObjects()) {
                animCps.add(cps); // add to animation Cps ArrayList
                unPos.x += cps.getPosition().x;
                unPos.y += cps.getPosition().y;
            }
            unPos.x /= animCps.size();
            unPos.y /= animCps.size();

            // save old Position
            savePos = new ArrayList<>();
            for (int i = 0; i < animCps.size(); i++) {
                savePos.add(new Position(0, 0));
                savePos.get(i).x = animCps.get(i).getPosition().x;
                savePos.get(i).y = animCps.get(i).getPosition().y;
            }

            animT = new javax.swing.Timer(animDelay, actionEvent1 -> {
                if (animDuration - animDelay > 0 && animCps.size() > 1) {
                    for (AbstractCpsObject animCpObject : animCps) {
                        double x1 = animCpObject.getPosition().x - unPos.x;
                        double y1 = animCpObject.getPosition().y - unPos.y;
                        animCpObject.getPosition().x -= x1 / animSteps;
                        animCpObject.getPosition().y -= y1 / animSteps;
                    }
                    repaint();
                    animDuration -= animDelay;
                    animSteps--;
                } else {
                    animDuration = ANIMTIME;
                    animSteps = animDuration / animDelay;
                    animT.stop();
                    for (int i = 0; i < animCps.size(); i++) {
                        animCps.get(i).getPosition().x = savePos.get(i).x;
                        animCps.get(i).getPosition().y = savePos.get(i).y;
                    }
                    controller.addUpperNode("NodeOfNode", null, animCps);
                    controller.calculateStateForCurrentTimeStep();
                    triggerUpdateController();
                    repaint();
                }
            });
            animT.start();
        });

        itemUngroup.addActionListener(actionEvent -> {
            // save old Position
            JTabbedPane tabbedPaneInner = (JTabbedPane) getParent().getParent().getParent();
            for (int i = 1; i < tabbedPaneInner.getTabCount(); i++) {
                if (((UpperNodeCanvas) ((JScrollPane) tabbedPaneInner.getComponentAt(i)).getViewport()
                        .getComponent(0)).upperNode.getId() == tempCps.getId()) {
                    tabbedPaneInner.remove(i);
                    break;
                }
            }

            savePos = new ArrayList<>();
            animCps = ((CpsUpperNode) tempCps).getNodes();
            controller.delUpperNode((CpsUpperNode) tempCps, null);

            for (int i = 0; i < animCps.size(); i++) {
                savePos.add(new Position(0, 0));
                savePos.get(i).x = animCps.get(i).getPosition().x;
                savePos.get(i).y = animCps.get(i).getPosition().y;
            }
            for (AbstractCpsObject cps : animCps) {
                int x = tempCps.getPosition().x;
                int y = tempCps.getPosition().y;

                cps.setPosition(new Position(x, y));
            }

            animT = new javax.swing.Timer(animDelay, actionEvent1 -> {
                if (animDuration - animDelay >= 0) {
                    for (int i = 0; i < animCps.size(); i++) {
                        double x1 = animCps.get(i).getPosition().x - savePos.get(i).x;
                        double y1 = animCps.get(i).getPosition().y - savePos.get(i).y;
                        animCps.get(i).getPosition().x -= x1 / animSteps;
                        animCps.get(i).getPosition().y -= y1 / animSteps;
                    }
                    repaint();
                    animDuration -= animDelay;
                    animSteps--;
                } else {
                    animDuration = ANIMTIME;
                    animSteps = animDuration / animDelay;
                    animT.stop();
                    for (int i = 0; i < animCps.size(); i++) {
                        animCps.get(i).getPosition().x = savePos.get(i).x;
                        animCps.get(i).getPosition().y = savePos.get(i).y;
                    }

                    controller.calculateStateForCurrentTimeStep();
                    triggerUpdateController();
                    repaint();
                }
            });
            animT.start();
        });

        // adds the selected object(s) to the statistic panel
        itemTrack.addActionListener(actionEvent -> {
            for (AbstractCpsObject o : model.getSelectedCpsObjects()) {
                boolean found = false;
                if (controller.getTrackingObj() != null) {
                    if (controller.getTrackingObj().contains(o)) {
                        found = true;
                    }
                }
                if (!found) {
                    controller.addTrackingObj(o);
                    if (o instanceof HolonObject) {
                        ((HolonObject) o).updateTrackingInfo();
                    }
                }
                if (model.getShowConsoleLog()) {
                    controller.addTextToConsole("Tracking: ", Color.BLACK, 12, false, false, false);
                    controller.addTextToConsole("" + o.getName(), Color.BLUE, 12, true, false, false);
                    controller.addTextToConsole(", ID:", Color.BLACK, 12, false, false, false);
                    controller.addTextToConsole("" + o.getId(), Color.RED, 12, true, false, true);
                }
            }
        });

        itemUntrack.addActionListener(actionEvent -> {
            for (AbstractCpsObject o : model.getSelectedCpsObjects()) {
                if (o instanceof HolonObject) {
                    boolean found = false;
                    if (controller.getTrackingObj() != null) {
                        for (AbstractCpsObject obj : controller.getTrackingObj()) {
                            if (obj instanceof HolonObject) {
                                if (obj.getId() == o.getId()) {
                                    found = true;
                                }
                            }
                        }
                    }
                    if (found) {
                        // Removed from tracking array and tracking
                        // information reseted
                        controller.removeTrackingObj(o);
                        ((HolonObject) o).setTrackingProd(new float[100]);
                        ((HolonObject) o).setTrackingCons(new float[100]);
                    }
                    if (model.getShowConsoleLog()) {
                        controller.addTextToConsole("Untracking: ", Color.BLACK, 12, false, false, false);
                        controller.addTextToConsole("" + o.getName(), Color.BLUE, 12, true, false, false);
                        controller.addTextToConsole(", ID:", Color.BLACK, 12, false, false, false);
                        controller.addTextToConsole("" + o.getId(), Color.RED, 12, true, false, true);
                    }
                }
            }
        });

        itemDelete.addActionListener(actionEvent -> {
            // Remove the selected Object objects
        	if(tempCps == null && edgeHighlight != null)
        	{
        		controller.removeEdgesOnCanvas(edgeHighlight);
        		edgeHighlight = null;
        	}
            boolean save = false;
            for (int j = 0; j < model.getSelectedCpsObjects().size(); j++) {
                AbstractCpsObject cps = model.getSelectedCpsObjects().get(j);
                if (j == model.getSelectedCpsObjects().size() - 1)
                    save = true;
                controller.delCanvasObject(cps, save);
                controller.removeTrackingObj(cps);
                // Remove UpperNodeTab if UpperNode deleted
                if (cps instanceof CpsUpperNode) {
                    JSplitPane tempSplit = (JSplitPane) getParent().getParent().getParent().getParent();
                    JTabbedPane tabbedPane;
                    JTabbedPane tabbedPane2;
                    // if SplitView is activated
                    if (tempSplit.getLeftComponent() instanceof JTabbedPane
                            && tempSplit.getRightComponent() instanceof JTabbedPane) {
                        tabbedPane = (JTabbedPane) tempSplit.getLeftComponent();
                        tabbedPane2 = (JTabbedPane) tempSplit.getRightComponent();
                    } else {
                        tabbedPane = (JTabbedPane) tempSplit.getLeftComponent();
                        tabbedPane2 = null;
                    }
                    // Look if the uppernode is open in a Tab
                    for (int i = 4; i < tabbedPane.getTabCount(); i++) {
                        if (tabbedPane.getComponentAt(i) != null
                                && ((UpperNodeCanvas) ((JScrollPane) tabbedPane.getComponentAt(i)).getViewport()
                                .getComponent(0)).upperNode.getId() == cps.getId()) {
                            ((ButtonTabComponent) tabbedPane.getTabComponentAt(i)).removeTabs();
                            break;
                        }
                    }
                    // If SplitView is on and the view on
                    // tabbedPane2 is the deleted upperNode
                    try {
                        if (tabbedPane2 != null
                                && ((UpperNodeCanvas) ((JScrollPane) tabbedPane2.getSelectedComponent())
                                .getViewport().getComponent(0)).upperNode.getId() == cps.getId()) {
                            ((ButtonTabComponent) tabbedPane.getTabComponentAt(tabbedPane2.getSelectedIndex()))
                                    .removeTabs();
                        }
                    } catch (Exception e2) {
                    }
                }
                toolTip = false;
            }
            model.getSelectedCpsObjects().clear();
            tempCps = null;
            repaint();
        });

        itemCut.addActionListener(actionEvent
                -> {
            controller.cut(null);
            itemPaste.setEnabled(true);
            repaint();
        });

        itemCopy.addActionListener(actionEvent -> {
            controller.copy(null);
            itemPaste.setEnabled(true);
            repaint();
        });

        itemPaste.addActionListener(actionEvent -> {
            try {
                controller.paste(null, mousePosition);
                unitGraph.update(model.getSelectedCpsObjects());

            } catch (JsonParseException | UnsupportedFlavorException | IOException e1) {
                JLabel message = new JLabel("The Clipboard information cannot be pastet into Application.");
                JOptionPane.showMessageDialog(null, message, "", JOptionPane.ERROR_MESSAGE);
            }
            repaint();
        });

        this.addMouseListener(this);
        this.addMouseMotionListener(this);
    }

    /**
     * Paints all Components on the Canvas.
     *
     * @param g Graphics
     */
    public void paintComponent(Graphics g) {
        String maxCap = null;
        super.paintComponent(g);
        // Rendering
        g2 = (Graphics2D) g;
        RenderingHints rh = new RenderingHints(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
        g2.setRenderingHints(rh);

        // Paint the Background
        if (!model.getCanvasImagePath().isEmpty()) {
            img = new ImageIcon(model.getCanvasImagePath()).getImage();
            switch (model.getCanvasImageMode()) {
                case BackgroundPopUp.IMAGE_PIXELS:
                    g2.drawImage(img, 0, 0, img.getWidth(null), img.getHeight(null), null);
                    break;
                case BackgroundPopUp.STRETCHED:
                    g2.drawImage(img, 0, 0, model.getCanvasX(), model.getCanvasY(), null);
                    break;
                case BackgroundPopUp.CUSTOM:
                    g2.drawImage(img, 0, 0, model.getCanvasImageWidth(), model.getCanvasImageHeight(), null);
                    break;
                default:
                    break;
            }
        }

        // SubNet Coloring
        int i = 0;
        for (SubNet s : controller.getSimManager().getSubNets()) {

            if (model.getSubNetColors().size() - 1 < i) {
                controller.addSubNetColor(new Color((int) (Math.random() * 255), (int) (Math.random() * 255),
                        (int) (Math.random() * 255)));
            }
            if (showedInformation[3]) {
                for (HolonObject cps : s.getObjects()) {
                    cps.setBorderColor(model.getSubNetColors().get(i));
                }
            }
            i++;
        }

        // drawEdges that is being dragged
        if (drawEdge) {
            g2.setColor(Color.BLACK);
            g2.setStroke(new BasicStroke(2));
            g2.drawLine(tempCps.getPosition().x, tempCps.getPosition().y, x, y);
        }

        for (CpsEdge con : model.getEdgesOnCanvas()) {
            maxCap = paintEdge(con, maxCap);
        }

        // Highlighted Edge
        if (model.getSelectedObjectID() > 0 || !model.getSelectedCpsObjects().isEmpty() || !tempSelected.isEmpty()) {
            g2.setColor(Color.BLUE);
            for (CpsEdge con : model.getEdgesOnCanvas()) {
                if (con.getFlow() <= con.getCapacity()) {
                    g2.setStroke(new BasicStroke(Math.min(((con.getFlow() / con.getCapacity() * 3) + 1), 4)));
                } else {
                    g2.setStroke(new BasicStroke(2));
                }

                maxCap = drawEdgeLine(con, maxCap);
            }
        } else if (edgeHighlight != null) {
            g2.setColor(Color.BLUE);
            if (edgeHighlight.getFlow() <= edgeHighlight.getCapacity()) {
                g2.setStroke(new BasicStroke(
                        Math.min(((edgeHighlight.getFlow() / edgeHighlight.getCapacity() * 3) + 1), 4)));
            } else {
                g2.setStroke(new BasicStroke(2));
            }
            g2.drawLine(edgeHighlight.getA().getPosition().x, edgeHighlight.getA().getPosition().y,
                    edgeHighlight.getB().getPosition().x, edgeHighlight.getB().getPosition().y);

            maxCap = setCapacityString(edgeHighlight, maxCap);

            if (showedInformation[0]) {
                g2.drawString(edgeHighlight.getFlow() + "/" + maxCap,
                        (edgeHighlight.getA().getPosition().x + edgeHighlight.getB().getPosition().x) / 2,
                        (edgeHighlight.getA().getPosition().y + edgeHighlight.getB().getPosition().y) / 2);
            }
        }

        // Objects
        for (AbstractCpsObject cps : model.getObjectsOnCanvas()) {
            // Border Highlighting
            if (showedInformation[3]) {
                g2.setColor(cps.getBorderColor());
                if (g2.getColor() != Color.WHITE && !(cps instanceof CpsNode)) {
                    g2.fillRect((int) (cps.getPosition().x - controller.getScaleDiv2() - scalediv20 - 3),
                            (int) (cps.getPosition().y - controller.getScaleDiv2() - scalediv20 - 3),
                            (int) (controller.getScale() + ((scalediv20 + 3) * 2)),
                            (int) (controller.getScale() + ((scalediv20 + 3) * 2)));
                }
            }

            setEdgePictureAndHighlighting(cps);

            g2.drawImage(img, cps.getPosition().x - controller.getScaleDiv2(),
                    cps.getPosition().y - controller.getScaleDiv2(), controller.getScale(), controller.getScale(),
                    null);

        }

        // Dragged marker Highlighting
        if (doMark) {
            g2.setColor(Color.BLACK);
            g2.setStroke(new BasicStroke(1));
            drawMarker();
        }
        // Tooltip
        showTooltip(g);
    }

    @Override
    public void mouseClicked(MouseEvent e) {
        if (e.getButton() == MouseEvent.BUTTON1) {
            if (model.getPropertyTable().getRowCount() > 0) {
                for (int i = model.getPropertyTable().getRowCount() - 1; i > -1; i--) {
                    model.getPropertyTable().removeRow(i);
                }
            }
            triggerUpdateController();
        }
    }

    @Override
    public void mouseEntered(MouseEvent e) {
    }

    @Override
    public void mouseExited(MouseEvent e) {
    }

    @Override
    public void mousePressed(MouseEvent e) {
        tempCps = null;
        edgeHighlight = null;
        controller.setSelecteEdge(null);
        // Object Selection
        for (AbstractCpsObject cps : model.getObjectsOnCanvas()) {
            cx = cps.getPosition().x - controller.getScaleDiv2();
            cy = cps.getPosition().y - controller.getScaleDiv2();
            if (x - controller.getScale() <= cx && y - controller.getScale() <= cy && x >= cx && y >= cy) {
                tempCps = cps;

                setConsoleTextAfterSelect(cps);

                dragging = true;
                if (e.isControlDown() && tempCps != null) {
                    if (model.getSelectedCpsObjects().contains(tempCps)) {
                        controller.deleteSelectedObject(tempCps);
                    } else {
                        controller.addSelectedObject(tempCps);
                    }

                }

                // If drawing an Edge (CTRL down)
                if (tempCps.getClass() == HolonObject.class) {
                    HolonObject tempObj = ((HolonObject) tempCps);
                    dataSelected = tempObj.getElements();
                }
                if (e.isShiftDown()) {
                    drawEdge = true;
                    dragging = false;
                }
            }
        }

        // Edge Selection
        if (tempCps == null) {
            edgeHighlight = mousePositionOnEdge(x, y);
            controller.setSelecteEdge(edgeHighlight);
            controller.setSelectedObjectID(0);
            if (!e.isControlDown() && e.getButton() != MouseEvent.BUTTON3) {
                model.getSelectedCpsObjects().clear();
            }
        }

        if (edgeHighlight == null && tempCps == null) {
            sx = e.getX();
            sy = e.getY();
            doMark = true;
        }

        repaint();
    }

    @Override
    public void mouseReleased(MouseEvent e) {
        x = e.getX();
        y = e.getY();

        dragging = false;

        if (drawEdge) {
            drawEdge = false;
            drawDeleteEdge();
        }

        if (dragged) {
            try {
                controller.autoSave();
            } catch (IOException ex) {
            	System.err.println("AutoSave error by dragging");
                ex.printStackTrace();
            }
        }

        if (!e.isControlDown() && !dragged && tempCps != null && MouseEvent.BUTTON3 != e.getButton()) {
            model.getSelectedCpsObjects().clear();
            controller.addSelectedObject(tempCps);
        }

        dragged = false;

        // Rightclick List
        setRightClickMenu(e);

        markObjects();

        if (doubleClick() && tempCps != null && tempCps instanceof HolonSwitch && MouseEvent.BUTTON3 != e.getButton()) {
            ((HolonSwitch) tempCps).switchState();
        }

        controller.calculateStateForTimeStep(model.getCurIteration());

        triggerUpdateController();

        repaint();

    }

    @Override
    public void mouseDragged(MouseEvent e) {
        // If Edge is drawn
        x = e.getX();
        y = e.getY();
        if (!model.getSelectedCpsObjects().contains(tempCps) && !doMark) {
            model.getSelectedCpsObjects().clear();
            if (tempCps != null) {
                controller.addSelectedObject(tempCps);
            }
        }
        if (dragging) {
            try {
                dragged = true;
                float xDist, yDist; // Distance

                x = e.getX();
                y = e.getY();

                // Make sure its in bounds
                if (e.getX() < controller.getScaleDiv2())
                    x = controller.getScaleDiv2();
                else if (e.getX() > this.getWidth() - controller.getScaleDiv2())
                    x = this.getWidth() - controller.getScaleDiv2();
                if (e.getY() < controller.getScaleDiv2())
                    y = controller.getScaleDiv2();
                else if (e.getY() > this.getHeight() - controller.getScaleDiv2())
                    y = this.getHeight() - controller.getScaleDiv2();

                // Distance
                xDist = x - tempCps.getPosition().x;
                yDist = y - tempCps.getPosition().y;

                tempCps.setPosition(x, y); // Drag Position
                // ToolTipText Position and name
                toolTip = true;
                toolTipText = tempCps.getName() + ", " + tempCps.getId();
                toolTipPos.x = tempCps.getPosition().x - controller.getScaleDiv2();
                toolTipPos.y = tempCps.getPosition().y + controller.getScaleDiv2();

                // All Selected Objects
                for (AbstractCpsObject cps : model.getSelectedCpsObjects()) {
                    if (cps != tempCps) {
                        x = (int) (cps.getPosition().x + xDist);
                        y = (int) (cps.getPosition().y + yDist);

                        // Make sure its in bounds
                        if (x <= controller.getScaleDiv2())
                            x = controller.getScaleDiv2();
                        else if (x > this.getWidth() - controller.getScaleDiv2())
                            x = this.getWidth() - controller.getScaleDiv2();
                        if (y <= controller.getScaleDiv2())
                            y = controller.getScaleDiv2();
                        else if (y > this.getHeight() - controller.getScaleDiv2())
                            y = this.getHeight() - controller.getScaleDiv2();

                        cps.setPosition(x, y);
                    }
                }
                repaint();
            } catch (Exception eex) {
            }
        }

        // Mark Objects
        if (doMark) {
            tempSelected.clear();
            for (AbstractCpsObject cps : model.getObjectsOnCanvas()) {
                int x1 = sx, x2 = x, y1 = sy, y2 = y;

                if (sx >= x) {
                    x1 = x;
                    x2 = sx;
                }
                if (sy >= y) {
                    y1 = y;
                    y2 = sy;
                }
                if (x1 <= cps.getPosition().x + model.getScaleDiv2() && y1 <= cps.getPosition().y + model.getScaleDiv2()
                        && x2 >= cps.getPosition().x && y2 >= cps.getPosition().y) {
                    tempSelected.add(cps);

                }
            }
        }

        repaint();

    }

    @Override
    public void mouseMoved(MouseEvent e) {
        x = e.getX();
        y = e.getY();

        // Everything for the tooltip :)
        boolean on = false;
        for (AbstractCpsObject cps : model.getObjectsOnCanvas()) {
            cx = cps.getPosition().x - controller.getScaleDiv2();
            cy = cps.getPosition().y - controller.getScaleDiv2();

            on = setToolTipInfoAndPosition(on, cps);
        }
        toolTip = on;
        repaint();
    }

    /**
     * Draws or Deletes an Edge.
     */
    void drawDeleteEdge() {
        if (getMousePosition() != null) {
            boolean node = true;
            boolean newEdge = true;
            boolean onEdge = true;
            boolean deleteNode = false;
            CpsEdge e = null;

            for (AbstractCpsObject cps : model.getObjectsOnCanvas()) {
                cx = cps.getPosition().x - controller.getScaleDiv2();
                cy = cps.getPosition().y - controller.getScaleDiv2();
                if (x - controller.getScale() <= cx
                        && y - controller.getScale() <= cy
                        && x >= cx && y >= cy
                        && cps != tempCps) {
                    node = false;
                    onEdge = false;
                    for (CpsEdge p : tempCps.getConnections()) {
                        if ((p.getA() == tempCps && p.getB() == cps) || (p.getB() == tempCps && p.getA() == cps)) {
                            newEdge = false;
                            e = p;
                        }
                    }
                    if (!newEdge) {
                        controller.removeEdgesOnCanvas(e);
                        // Node ohne Edge?
                        if (e.getA().getClass() == CpsNode.class && e.getA().getConnections().isEmpty()) {
                            tempCps = e.getA();
                            deleteNode = true;
                        }
                        if (e.getB().getClass() == CpsNode.class && e.getB().getConnections().isEmpty()) {
                            deleteNode = true;
                        }
                    } else {
                        e = new CpsEdge(cps, tempCps, model.getMaxCapacity());
                        controller.addEdgeOnCanvas(e);
                    }
                }
            }
            // Edge auf eine Edge gezogen?
            if (onEdge) {
                CpsEdge p = mousePositionOnEdge(x, y);
                if (p != null) {
                    CpsEdge e1;
                    CpsEdge e2;

                    node = false;

                    CpsNode n = new CpsNode("Node");

                    n.setPosition(x, y);
                    controller.addObjectCanvas(n);

                    AbstractCpsObject r, k;
                    r = p.getA();
                    k = p.getB();

                    e = new CpsEdge(n, tempCps, model.getMaxCapacity());

                    e1 = new CpsEdge(n, r, model.getMaxCapacity());

                    e2 = new CpsEdge(n, k, model.getMaxCapacity());

                    controller.removeEdgesOnCanvas(p);
                    controller.addEdgeOnCanvas(e);
                    controller.addEdgeOnCanvas(e1);
                    controller.addEdgeOnCanvas(e2);
                }
            }

            // ins leere Gedragged
            if (node) {
                CpsNode n = new CpsNode("Node");

                n.setPosition(x, y);
                controller.addObjectCanvas(n);

                e = new CpsEdge(n, tempCps, model.getMaxCapacity());

                controller.addEdgeOnCanvas(e);
            }

            // Wenn ein Node ohne Connections da ist
            if (deleteNode) {
                controller.delCanvasObject(tempCps, true);
                tempCps = null;
            }
        }
    }

    /**
     * Checks if the mouse is on an Edge.
     *
     * @param x Position of the Mouse
     * @param y Position of the Mouse
     * @return CpsEdge the Mouse is on, null if the mouse is not on an Edge
     */
    private CpsEdge mousePositionOnEdge(int x, int y) {
        x += controller.getScaleDiv2();
        y += controller.getScaleDiv2();
        for (CpsEdge p : model.getEdgesOnCanvas()) {
            Line2D l = new Line2D.Float(p.getA().getPosition().x, p.getA().getPosition().y, p.getB().getPosition().x,
                    p.getB().getPosition().y);

            int[] positions = determineMousePositionOnEdge(p);
            int lx = positions[0];
            int ly = positions[1];
            int hx = positions[2];
            int hy = positions[3];

            // distance from a point to a line and between both Objects
            if (l.ptLineDistSq(x - model.getScaleDiv2(), y - model.getScaleDiv2()) < 20 && x > lx && x < hx && y > ly
                    && y < hy) {
                return p;
            }
        }
        return null;
    }
    

    void updateLanguages() {
        itemCut.setText(Languages.getLanguage()[95]);
        itemCopy.setText(Languages.getLanguage()[96]);
        itemPaste.setText(Languages.getLanguage()[97]);
        itemDelete.setText(Languages.getLanguage()[98]);
        itemGroup.setText(Languages.getLanguage()[99]);
        itemUngroup.setText(Languages.getLanguage()[100]);
        itemTrack.setText(Languages.getLanguage()[101]);
        itemUntrack.setText(Languages.getLanguage()[102]);
    }

    /**
     * Set if Information should be shown.
     *
     * @param connection boolean for conecction
     * @param object     boolean for objects
     * @param nodeOfnode
     */
    void setShowedInformation(boolean connection, boolean object, boolean border, boolean nodeOfnode) {
        showedInformation[0] = connection;
        showedInformation[1] = object;
        showedInformation[3] = border;
        showedInformation[4] = nodeOfnode;
    }

    /**
     * Returns if Information should be shown.
     *
     * @return Array of boolean [0] = connection, [1] = objects
     */
    boolean[] getShowedInformation() {
        return showedInformation;
    }

    /**
     * set toolTip
     *
     * @param bool
     */
    void setToolTip(boolean bool) {
        this.toolTip = bool;
    }

    /**
     * Set the Mouse
     *
     * @param x
     * @param y
     */
    void setXY(int x, int y) {
        this.x = x;
        this.y = y;
    }

}