package de.renew.fa.gui;

import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;

import de.renew.faformalism.FAFormalismPlugin;
import de.renew.faformalism.util.FAAutomatonModelEnum;
import de.renew.faformalism.util.SimulationSettingsManager;
import de.renew.formalism.FormalismPlugin;
import de.renew.simulator.api.SimulationManager;

class FASimulationSettingsGui implements FASimulationSettingsInterface {

    private final JFrame _frame;

    private final JPanel _textFieldPanel = new JPanel();

    private final JComboBox<FAAutomatonModelEnum> _automatonModelComboBox;

    private boolean _simulateWordMode = true;
    private boolean _manualSimulation = true;
    private JRadioButton _manual;
    private JButton _simulateWordModeButton;

    private ActionListener _simulateWordModeActionListener;
    private ActionListener _manualSimulationActionListener;
    private ActionListener _automationModelComboBoxActionListener;

    private FAAutomatonModelEnum _previousSelection = FAAutomatonModelEnum.NFA;

    private final static FAAutomatonModelEnum[] MODELS =
        { FAAutomatonModelEnum.NFA, FAAutomatonModelEnum.BUECHI, FAAutomatonModelEnum.PDA
        //add more if implemented
        };

    FASimulationSettingsGui() {

        _frame = new JFrame("FA Automaton Settings");

        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));

        /* top panel */
        JPanel modePanel = new JPanel();
        modePanel.setLayout(new BoxLayout(modePanel, BoxLayout.X_AXIS));
        modePanel.add(createHorizontalFiller());
        _simulateWordModeButton = new JButton("Switch Mode");
        JLabel currentMode = new JLabel("<html><B>Current Mode:</B> Simulate Word</html>");
        _simulateWordModeActionListener = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (SimulationManager.isSimulationActive()) {
                    return;
                }
                String text = "<html><B>Current Mode:</B> ";
                if (!_simulateWordMode) {
                    text += "Simulate Word";
                } else {
                    text += "Build Word";
                    _manualSimulation = true;
                    _manual.setSelected(true);
                }
                _simulateWordMode = !_simulateWordMode;
                SimulationSettingsManager.setSimulateWordMode(_simulateWordMode);
                currentMode.setText(text + "</html>");
                modePanel.revalidate();
                modePanel.repaint();
                _textFieldPanel.revalidate();
                _textFieldPanel.repaint();
            }
        };
        _simulateWordModeButton.addActionListener(_simulateWordModeActionListener);
        modePanel.add(currentMode);
        modePanel.add(_simulateWordModeButton);

        JPanel modelPanel = new JPanel();
        modelPanel.setLayout(new BoxLayout(modelPanel, BoxLayout.X_AXIS));
        modelPanel.add(createHorizontalFiller());
        _automatonModelComboBox = new JComboBox<>(MODELS);
        FAAutomatonModelEnum current = SimulationSettingsManager.getAutomatonModel();
        if (current != FAAutomatonModelEnum.NET) {
            _automatonModelComboBox.setSelectedItem(SimulationSettingsManager.getAutomatonModel());
        } else {
            _automatonModelComboBox.setSelectedItem(_previousSelection);
        }
        _automationModelComboBoxActionListener = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (SimulationManager.isSimulationActive()) {
                    _automatonModelComboBox.setSelectedItem(_previousSelection);
                    return;
                }
                _previousSelection =
                    (FAAutomatonModelEnum) _automatonModelComboBox.getSelectedItem();
                SimulationSettingsManager.setAutomatonModel(_previousSelection);
            }
        };
        _automatonModelComboBox.addActionListener(_automationModelComboBoxActionListener);
        modelPanel.add(_automatonModelComboBox);
        modelPanel.add(createHorizontalFiller());

        JPanel manualPanel = new JPanel();
        manualPanel.setLayout(new BoxLayout(manualPanel, BoxLayout.X_AXIS));
        manualPanel.add(createHorizontalFiller());
        _manual = new JRadioButton("Manual simulation");
        _manual.setSelected(true);
        _manualSimulationActionListener = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (SimulationManager.isSimulationActive() || !_simulateWordMode) {
                    _manual.setSelected(_manualSimulation);
                    return;
                }
                _manualSimulation = !_manualSimulation;
                SimulationSettingsManager.setManualSimulation(_manualSimulation);
            }
        };
        _manual.addActionListener(_manualSimulationActionListener);
        manualPanel.add(_manual);
        manualPanel.add(createHorizontalFiller());

        mainPanel.add(modePanel);
        mainPanel.add(modelPanel);
        mainPanel.add(manualPanel);

        mainPanel.add(_textFieldPanel);

        _frame.add(mainPanel);
        _frame.setDefaultCloseOperation(JFrame.HIDE_ON_CLOSE);
        _frame.pack();
        _frame.setMinimumSize(_frame.getSize());
    }

    /**
     * A convenience method to create a filler component.
     *
     * @return a horizontal filler component
     */
    private Box.Filler createHorizontalFiller() {
        return new Box.Filler(new Dimension(0, 0), new Dimension(20, 0), new Dimension(1000, 0));
    }

    @Override
    public FAAutomatonModelEnum getSelectedAutomatonType() {
        return (FAAutomatonModelEnum) _automatonModelComboBox.getSelectedItem();
    }

    @Override
    public boolean simulateWordMode() {
        return _simulateWordMode;
    }

    @Override
    public void showGui() {
        FormalismPlugin fp = FormalismPlugin.getCurrent();
        if (fp != null && !fp.getCompiler().equals(FAFormalismPlugin.FA_AUTOMATON_COMPILER_NAME)) {
            String message =
                "The current formalism is not affected by the settings chosen from this menu.\n"
                    + " Chose the \"FA Automaton Compiler\" if you want to simulate automata processing expressions.";
            JOptionPane.showMessageDialog(
                new JFrame(), message, "Wrong Formalism", JOptionPane.ERROR_MESSAGE);
            return;
        }
        _frame.setVisible(true);
        _frame.setState(java.awt.Frame.NORMAL);
        _frame.toFront();
        _frame.repaint();
    }

    public void cleanup() {
        _frame.dispose();
    }
}
