package org.artisanlogiciel.games.maze.gui;

import org.artisanlogiciel.games.maze.MazeParams;
import org.artisanlogiciel.games.maze.MazeParamsFixed;
import org.artisanlogiciel.games.stl.Maze3dParams;

import javax.swing.*;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

public class MazeControler extends JPanel {
    /**
     *
     */
    private static final long serialVersionUID = 1L;

    private final Display display;
    private MazeSettings settings = null;

    JSlider layerSlide = null;


    private void setMazeName(String pName) {
        MazeParamsFixed p = (MazeParamsFixed) display.getParams();
        p.setName(pName);
    }

    private JMenu createCreateMenu() {
        JMenu createMenu = new JMenu(MazeDefault.labels.getString("create"));

        JButton buttonCreate = new JButton(MazeDefault.labels.getString("create"));
        buttonCreate.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                display.recreateModel();
            }
        });

        createMenu.add(buttonCreate);

        createMenu.add(getGenerationControl());

        JButton buttonReset = new JButton("reset");//labels.getString("reset"));
        buttonReset.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                display.resetModel();
            }
        });
        createMenu.add(buttonReset);

        return createMenu;
    }

    private JMenu createLoadingMenu() {
        JMenu loadMenu = new JMenu(MazeDefault.labels.getString("load"));

        final JTextField loadName = new JTextField("newlaby");

        loadMenu.add(loadName);

        Action loadRawAction = new AbstractAction() {
            public void actionPerformed(ActionEvent evt) {
                //
                display.addStatus("load raw");

                String filename = loadName.getText();

                if ((filename.length() > 0)) {
                    setMazeName(filename);
                    display.loadRaw();
                    display.refresh();
                }

            }
        };
        JButton loadRawButton = new JButton(MazeDefault.labels.getString("load") + " raw");
        loadRawButton.addActionListener(loadRawAction);
        loadMenu.add(loadRawButton);

        Action loadImcAction = new AbstractAction() {
            public void actionPerformed(ActionEvent evt) {
                //
                display.addStatus("load Imc");

                String filename = loadName.getText();

                if ((filename.length() > 0)) {
                    setMazeName(filename);
                    display.loadImc(false);
                    display.refresh();
                }

            }
        };
        JButton loadImcButton = new JButton(MazeDefault.labels.getString("load") + " imc");
        loadImcButton.addActionListener(loadImcAction);

        loadMenu.add(loadImcButton);

        Action loadDrawingAction = new AbstractAction() {
            public void actionPerformed(ActionEvent evt) {
                //
                display.addStatus("load Drawing");

                String filename = loadName.getText();

                if ((filename.length() > 0)) {
                    setMazeName(filename);
                    display.loadDrawing(false);
                    display.refresh();
                }

            }
        };
        JButton loadDrawingButton = new JButton(MazeDefault.labels.getString("load") + " Drawing");
        loadDrawingButton.addActionListener(loadDrawingAction);

        loadMenu.add(loadDrawingButton);

        Action loadOsmAction = new AbstractAction() {
            public void actionPerformed(ActionEvent evt) {
                //
                display.addStatus("load Osm");

                String filename = loadName.getText();

                if ((filename.length() > 0)) {
                    setMazeName(filename);
                    // UTM 32T ? approx (long,lat) to meter
                    display.loadOsm(false, 78000, 78000);
                    display.refresh();
                }

            }
        };
        loadMenu.add(newLoadButton("osm", loadOsmAction));

        loadMenu.add(newLoadButton("we",
                new AbstractAction() {
                    public void actionPerformed(ActionEvent evt) {
                        //
                        display.addStatus("load WoldEdit");

                        String filename = loadName.getText();

                        if ((filename.length() > 0)) {
                            setMazeName(filename);
                            display.loadWorldEdit(false);
                            display.refresh();
                        }

                    }
                }
        ));
        return loadMenu;
    }

    private JMenu createSavingMenu() {
        final JTextField saveName = new JTextField("newlaby");

        final JButton savePngButton = newSaveButton("png",
                new AbstractAction() {
                    public void actionPerformed(ActionEvent evt) {
                        //
                        display.addStatus("save png");
                        setMazeName(saveName.getText());
                        display.savePng();
                    }
                });

        final JButton saveSvgButton = newSaveButton("svg",
                new AbstractAction() {
                    public void actionPerformed(ActionEvent evt) {
                        display.writeSentence("save svg");
                        setMazeName(saveName.getText());
                        display.saveSvg();
                    }
                });

        final JButton saveButton = newSaveButton("raw",
                new AbstractAction() {
                    public void actionPerformed(ActionEvent evt) {
                        setMazeName(saveName.getText());
                        MazeParamsFixed p = (MazeParamsFixed) display.getParams();
                        display.saveRaw(p);
                    }
                });

        Action saveImcAction = new AbstractAction() {
            public void actionPerformed(ActionEvent evt) {
                setMazeName(saveName.getText());
                display.saveImc();
            }
        };
        final JButton saveImcButton = newSaveButton("imc", saveImcAction);

        Action saveStlAction = new AbstractAction() {
            public void actionPerformed(ActionEvent evt) {
                //
                setMazeName(saveName.getText());
                MazeParamsFixed p = (MazeParamsFixed) display.getParams();
                display.saveStl(p, display.stlsettings.createParams());
            }
        };
        final JButton saveStlButton = newSaveButton("stl", saveStlAction);

        Action saveTextAction = new AbstractAction() {
            public void actionPerformed(ActionEvent evt) {
                //
                setMazeName(saveName.getText());
                display.saveText();
            }
        };
        final JButton saveTextButton = newSaveButton("txt", saveTextAction);

        final JButton saveWorleEditButton = newSaveButton("we",
                new AbstractAction() {
                    public void actionPerformed(ActionEvent evt) {
                        setMazeName(saveName.getText());
                        display.saveWorldEdit();
                    }
                });

        display.stlsettings = new Maze3dSettings(new Maze3dParams());

        JMenu saveMenu = new JMenu(MazeDefault.labels.getString("save"));
        saveMenu.add(saveName);
        saveMenu.add(saveSvgButton);
        saveMenu.add(savePngButton);
        saveMenu.add(saveButton);
        saveMenu.add(display.stlsettings);
        saveMenu.add(saveStlButton);
        saveMenu.add(saveImcButton);
        saveMenu.add(saveTextButton);
        saveMenu.add(saveWorleEditButton);

        return saveMenu;

    }

    private JButton newActionButton(String actionName, String format, Action action) {
        final JButton saveTextButton = new JButton(MazeDefault.labels.getString(actionName) + " " + format);
        saveTextButton.addActionListener(action);
        return saveTextButton;
    }

    private JButton newSaveButton(String format, Action action) {
        return newActionButton("save", format, action);
    }

    private JButton newLoadButton(String format, Action action) {
        return newActionButton("load", format, action);
    }

    private JPanel createPaletteChooser()
    {
        return new JPanel(new FlowLayout());
    }

    private JPanel createResolveQuitBar() {
        JPanel resolveQuitBar = new JPanel(new FlowLayout());

        JButton resolveButton = new JButton(MazeDefault.labels.getString("resolve"));
        resolveButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                //
                display.addStatus("Resolving");
                display.resolve();
            }
        });

        resolveQuitBar.add(resolveButton);

        JButton reverseButton = new JButton(MazeDefault.labels.getString("reverse"));
        reverseButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                //
                display.addStatus("Reversing");
                display.mGrow ^= display.reverse(display.mGrow);
            }
        });

        resolveQuitBar.add(reverseButton);


        final JButton quitButton = new JButton(MazeDefault.labels.getString("quit"));
        Action quitAction = new AbstractAction() {
            public void actionPerformed(ActionEvent evt) {
                //
                display.addStatus("quit");
                System.exit(0);
            }
        };
        quitButton.addActionListener(quitAction);

        resolveQuitBar.add(quitButton);

        return resolveQuitBar;

    }

    public MazeControler(Display display, MazeParams params) {
        // super(new BorderLayout());
        super();
        this.display = display;
        BoxLayout layout = new BoxLayout(this, BoxLayout.Y_AXIS);
        setLayout(layout);

        settings = new MazeSettings(params);

        JMenuBar menuBar = new JMenuBar();
        menuBar.add(createCreateMenu());
        menuBar.add(createSavingMenu());
        menuBar.add(createLoadingMenu());
        add(menuBar);

        add(createResolveQuitBar());

        JPanel controlMovesPanel = new JPanel(new BorderLayout());

        @SuppressWarnings("serial")
        Action goNorth = new AbstractAction() {
            public void actionPerformed(ActionEvent evt) {
                //
                display.addStatus("go North");
                display.goNorth();
            }
        };
        JButton north = display.addDirection(this, MazeDefault.labels.getString("north"), "UP", goNorth);

        @SuppressWarnings("serial")
        Action goEast = new AbstractAction() {
            public void actionPerformed(ActionEvent evt) {
                //
                display.addStatus("go East");
                display.goEast();
            }
        };

        JButton east = display.addDirection(this, MazeDefault.labels.getString("east"), "RIGHT", goEast);

        @SuppressWarnings("serial")
        Action goWest = new AbstractAction() {
            public void actionPerformed(ActionEvent evt) {
                //
                display.addStatus("go West");
                display.goWest();
            }
        };
        JButton west = display.addDirection(this, MazeDefault.labels.getString("west"), "LEFT", goWest);

        @SuppressWarnings("serial")
        Action goSouth = new AbstractAction() {
            public void actionPerformed(ActionEvent evt) {
                //
                display.addStatus("go South");
                display.goSouth();
            }
        };
        JButton south = display.addDirection(this, MazeDefault.labels.getString("south"), "DOWN", goSouth);

        controlMovesPanel.add(north, BorderLayout.NORTH);
        controlMovesPanel.add(west, BorderLayout.WEST);
        controlMovesPanel.add(east, BorderLayout.EAST);
        controlMovesPanel.add(south, BorderLayout.SOUTH);

        JPanel controlPanel = new JPanel();

        controlPanel.add(controlMovesPanel, BorderLayout.LINE_START);
        display.statusField = new JTextField("", 20);
        controlPanel.add(display.statusField, BorderLayout.CENTER);
        add(controlPanel, BorderLayout.NORTH);

        // control display panel contains controls for display
        final JPanel controlDisplayPanel = new JPanel(new BorderLayout());

        add(controlDisplayPanel);
        // zoom , autozoom control
        add(buildResizeControl());
        // layers control
        add(buildLayerControl());

        // NOPE ! it overrides menu belonging
        // add(settings);

    }

    private JPanel buildResizeControl() {
        final JCheckBox showAll = new JCheckBox("show all");
        showAll.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                display.maze.setShowAll(showAll.isSelected());
            }
        });

        final JSlider slider = new JSlider(2, 40);
        slider.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                display.setWallSize(slider.getValue());
            }
        });
        final JCheckBox autoSlide = new JCheckBox("autoslide");
        autoSlide.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                display.setAutoSize(autoSlide.isSelected());
            }
        });

        final JCheckBox hexagon = new JCheckBox("hexagon");
        hexagon.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                display.setHexagon(hexagon.isSelected());
            }
        });

        final JCheckBox background = new JCheckBox("background");
        background.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                display.setBackground(background.isSelected());
            }
        });

        JPanel resizecontrol = new JPanel(new FlowLayout());
        resizecontrol.add(showAll);
        resizecontrol.add(slider);
        resizecontrol.add(autoSlide);
        resizecontrol.add(hexagon);
        resizecontrol.add(background);

        return resizecontrol;

    }

    private JPanel buildLayerControl() {

        int layers = 10;

        final JTextField layersText = new JTextField("" + layers);

        layerSlide = new JSlider(JSlider.HORIZONTAL, 0, layers, 0);
        layerSlide.addChangeListener(new ChangeListener() {
            public void stateChanged(ChangeEvent e) {
                int r = display.setLayer(layerSlide.getValue());
                //layerSlide.setMaximum(r);
            }
        });
        layerSlide.setMajorTickSpacing(1);
        layerSlide.setPaintTicks(true);

        JPanel layerControl = new JPanel(new FlowLayout());
        layerControl.add(new JLabel("layers"));
        layerControl.add(layersText);
        layerControl.add(layerSlide);

        return layerControl;

    }

    public int getLayer() {
        return layerSlide.getValue();
    }

    JPanel getMoveControl() {
        return this;
    }

    JPanel getGenerationControl() {
        return settings;
    }

    public MazeSettings getSettings() {
        return settings;
    }

}
