package jnet.client.gui;

import jnet.client.gui.dialog.ObjectDialog;
import jnet.client.Client;
import jnet.client.ExtAppManager;
import jnet.client.gui.dialog.DialogLocalPing;
import jnet.client.network.NettyClient;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.util.Iterator;
import javax.swing.ImageIcon;
import javax.swing.JMenuItem;
import javax.swing.JPopupMenu;
import jnet.lib.Message;
import jnet.lib.object.Map;
import jnet.lib.object.MapObject;

public class MapViewAction implements MouseMotionListener, MouseListener {

    private Map map;

    public MapViewAction(Map map) {
        this.map = map;

    }

    private static PaintObject selectedObject;
    private static Point offset;
    public static boolean createConnection = false;
    public static PaintObject startConMapObject;
    public static PaintObject endConMapObject;
    public static Point endConnPoint;

    @Override
    public void mouseClicked(MouseEvent e) {
        // vola se pri kliknuti v mape
    }

    @Override
    public void mousePressed(MouseEvent e) { // vola se pri stisknuti tlacitka
        // vyhledani jestli se kliklo na nejaky objekt
        if (MapView.paintObjects == null) {
            return;
        }
        for (PaintObject node : MapView.paintObjects) {
            // zruseni vybrani na vsech objektech
            node.setSelected(false);
            if (node.contains(e.getPoint())) {
                if (createConnection) { // vytvareni propojeni - startovni body 
                    startConMapObject = node;
                    endConnPoint = e.getPoint();
                } else {
                    selectedObject = node;
                    // nastaveni vybraneho objektu
                    offset = new Point(
                            (int) selectedObject.getBoxX() - e.getX(),
                            (int) selectedObject.getBoxY() - e.getY()
                    );
                    // zvyrazneni vybraneho objektu
                    selectedObject.setSelected(true);
                }
            }
        }
    }

    @Override
    public void mouseReleased(MouseEvent e) { // vola se pri uvolneni tlacitka 
        if (selectedObject != null) {
            // presouvani objektu
            if (!map.isLock()) {// povoli upravy jen kdyz neni mapa zamcena 
                // odeslani nove pozice objektu
                // TODO doresit kontrolu souradnic aby se zbytecne neodesilala zmena kdyz k ni nedojde
                // zkontrolovat zda došlo ke zmene pozice
                int[] data = {
                    selectedObject.getId(),
                    (int) selectedObject.getX(),
                    (int) selectedObject.getY()
                };
                NettyClient.send(Message.OBJECT_MOVE, data);
            }
            // dvojklik na objekt
            if (e.getClickCount() == 2) {
                doubleClickOnObject(selectedObject);
            }
            // prave kliknuti na objekt
            if (e.getButton() == MouseEvent.BUTTON3) {
                rightClickOnObject(e, selectedObject);
            }
        } else {
            // prave kliknuti do volneho mista v mape
            if (e.getButton() == MouseEvent.BUTTON3) {
                rigthClick(e);
            }
        }
        selectedObject = null;
        offset = null;

        if (createConnection) {
            for (PaintObject node : MapView.paintObjects) {
                if (node.contains(e.getPoint())) {
                    endConMapObject = node;
                    if (startConMapObject.getId() != endConMapObject.getId()) {
                        //new ObjectConnectionDialog(startConMapObject.getId(), endConMapObject.getId());
                    }
                }
            }
            // zrusi vytvareni propojeni 
            createConnection = false;
        }
    }

    @Override
    public void mouseEntered(MouseEvent e) {
        // vola se pri vstupu kurzoru
    }

    @Override
    public void mouseExited(MouseEvent e) {
        // vola se pri opusteni kurzoru 
    }

    @Override
    public void mouseDragged(MouseEvent e) {
        //jen pokud neni mapa zamcena 
        if (!map.isLock() && Client.user.isEditMap()) {
            // vytvareni propojeni
            if (createConnection) {
                for (PaintObject node : MapView.paintObjects) {
                    if (node.contains(e.getPoint())) {
                        endConnPoint = node.getPoint();
                        break;
                    } else {
                        endConnPoint = e.getPoint();
                    }
                }
            } else {
                // presunovani objektu
                if (this.selectedObject != null && this.offset != null) {
                    // ziskani novych souradnic
                    Point to = e.getPoint();
                    to.x += offset.x;
                    to.y += offset.y;
                    //nastaveni nove pozice
                    selectedObject.setPosition(to);
                }
            }
        }
    }

    @Override
    public void mouseMoved(MouseEvent e) {

    }

    private void doubleClickOnObject(PaintObject selectedObject) {
        int id = selectedObject.getId();
        for (Map map : Client.maps) {
            for (MapObject object : map.getObjects()) {
                if (object.getId() == id) {
                    new ObjectDialog(map.getId(), object, false);
                    break;
                }
            }
        }
    }

    private void rigthClick(MouseEvent me) {
        JPopupMenu menu = new JPopupMenu();
        // zamek mapy
        JMenuItem itemLock;
        if (map.isLock()) {
            itemLock = new JMenuItem("Odemknout mapu", new ImageIcon("img/unlock.png"));
        } else {
            itemLock = new JMenuItem("Zamknout mapu", new ImageIcon("img/lock.png"));
        }
        itemLock.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (map.isLock()) {
                    int[] d = {map.getId(), 0};
                    NettyClient.send(Message.SET_MAP_LOCK, d);
                } else {
                    int[] d = {map.getId(), 1};
                    NettyClient.send(Message.SET_MAP_LOCK, d);
                }
            }
        });
        menu.add(itemLock);

        // polozka pridat objekt 
        if (Client.user.isAddObject()) {
            JMenuItem itemAdd = new JMenuItem("Přidat objekt", new ImageIcon("img/add.png"));
            itemAdd.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    MapObject mo = new MapObject();
                    mo.setX(me.getX());
                    mo.setY(me.getY());
                    new ObjectDialog(map.getId(), mo, true);
                }
            });
            itemAdd.setEnabled(!map.isLock());
            menu.add(itemAdd);
        }
        // polozka pridani propojeni
        /*
            JMenuItem itemPropoj = new JMenuItem("Přidat propojení", new ImageIcon("img/arrow.png"));
            itemPropoj.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    startConMapObject = null;
                    endConnPoint = null;
                    createConnection = true;
                }
            });
            menu.add(itemPropoj);
         */

        menu.show(me.getComponent(), me.getX(), me.getY());
    }

    private void rightClickOnObject(MouseEvent e, PaintObject obj) {
        JPopupMenu menu = new JPopupMenu();
        if (obj.getObject().isWinbox()) {
            JMenuItem itemWinbox = new JMenuItem("Winbox", new ImageIcon("img/winbox.png"));
            itemWinbox.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    //AppLauncher.winbox(obj.getObject().getIp(), obj.getObject().getService().getPortWinbox(), obj.getObject().getUser(), obj.getObject().getPassword());
                    new ExtAppManager().runWinbox(obj.getObject().getIp(), obj.getObject().getUser(), obj.getObject().getPassword(), Integer.valueOf(obj.getObject().getWinboxPort()));
                }
            });
            menu.add(itemWinbox);
        }
        if (obj.getObject().isWeb()) {
            JMenuItem itemWeb = new JMenuItem("Otevřít v prohlížeči", new ImageIcon("img/browser.png"));
            itemWeb.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    new ExtAppManager().runWeb(obj.getObject().getWebVerze(), obj.getObject().getIp(), obj.getObject().getWebPort());
                }
            });
            menu.add(itemWeb);
        }
        if (obj.getObject().isSsh()) {
            JMenuItem itemSsh = new JMenuItem("SSH", new ImageIcon("img/ssh.png"));
            itemSsh.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    new ExtAppManager().runSshPutty(obj.getObject().getIp(), obj.getObject().getUser(), obj.getObject().getPassword(), Integer.parseInt(obj.getObject().getSshPort()));
                    //AppLauncher.ssh(obj.getObject().getIp(), obj.getObject().getUser(), obj.getObject().getPassword(), Integer.parseInt(obj.getObject().getService().getPortSsh()));
                }
            });
            menu.add(itemSsh);
        }

        // ping na objekt
        JMenuItem itemPingRemote = new JMenuItem("Ping", new ImageIcon("img/ping.png"));
        itemPingRemote.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
            }
        });
        menu.add(itemPingRemote);

        // ping na objekt
        JMenuItem itemPingLocal = new JMenuItem("Ping (lokální)", new ImageIcon("img/ping.png"));
        itemPingLocal.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                DialogLocalPing dp = new DialogLocalPing(obj.getObject().getIp());
                Thread pingThread = new Thread(dp);
                pingThread.start();
            }
        });
        menu.add(itemPingLocal);

        // odebrani objektu
        if (Client.user.isRemoveObject()) {
            JMenuItem itemRemove = new JMenuItem("Odebrat", new ImageIcon("img/trash.png"));
            itemRemove.addActionListener(new ActionListener() {
                @Override
                public void actionPerformed(ActionEvent e) {
                    NettyClient.send(Message.REMOVE_OBJECT, obj.getId());
                }
            });
            itemRemove.setEnabled(!map.isLock());
            menu.add(itemRemove);
        }

        // zobrazeni menu
        menu.show(e.getComponent(), e.getX(), e.getY());
    }

}
