package de.renew.fa.gui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.util.HashSet;
import java.util.Set;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

import CH.ifa.draw.IOHelper;
import CH.ifa.draw.framework.DrawingTypeManager;
import CH.ifa.draw.io.DrawingFileHelper;
import de.renew.fa.FADrawing;
import de.renew.fa.FAPlugin;
import de.renew.fa.service.AutomataComparator;
import de.renew.fa.util.FAHelper;
import de.renew.faformalism.util.FASyntaxChecker;


public class FACompareGui {

    private final JFrame _frame;
    private final JPanel _leftPanel;
    private final Set<FADrawing> _rightDrawings = new HashSet<>();

    private boolean _regexSelected = false;
    private JTextField _regexInputField;
    private final JButton _leftSwitchButton;
    private final JButton _changeDrawingButton;
    private final JButton _compareButton;
    private final JButton _addButtonRight;
    private final JButton _removeAllButton;

    private FADrawing _leftDrawing;

    private final ActionListener _changeDrawingButtonListener;
    private final ActionListener _leftSwitchButtonListener;
    private final ActionListener _compareButtonListener;
    private final ActionListener _addRightButtonListener;
    private final ActionListener _removeAllButtonListener;


    /**
     * Initializes the gui, and shows it to the user.
     */
    public FACompareGui() {
        _frame = new JFrame("Compare Automata");
        JPanel mainPanel = new JPanel();
        mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.X_AXIS));

        /*------------ create left side ------------*/
        _leftPanel = new JPanel();
        _leftPanel.setLayout(new BoxLayout(_leftPanel, BoxLayout.Y_AXIS));
        _changeDrawingButton = new JButton("Change Drawing");
        _changeDrawingButtonListener = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JFileChooser chooser = new JFileChooser(System.getProperty("user.dir"));
                chooser.setFileFilter(
                    IOHelper.mapToSwingFileFilter(
                        DrawingTypeManager.getInstance().getFilter(FAPlugin.FA_FILEFILTER)));
                chooser.setAcceptAllFileFilterUsed(false);
                chooser.setMultiSelectionEnabled(false);
                int success = chooser.showOpenDialog(null);
                if (success != JFileChooser.APPROVE_OPTION) {
                    return;
                }
                File file = chooser.getSelectedFile();
                JLabel drawingName = new JLabel(file.getName());
                drawingName.setHorizontalAlignment(JLabel.HORIZONTAL);
                _leftDrawing = (FADrawing) DrawingFileHelper.loadDrawing(file, message -> {
                });
                _leftPanel.remove(0);
                _leftPanel.add(drawingName, 0);
                _frame.revalidate();
                _frame.pack();
                _frame.repaint();
            }
        };
        _changeDrawingButton.addActionListener(_changeDrawingButtonListener);
        JLabel defaultText = new JLabel("No drawing selected");
        _leftPanel.add(defaultText);
        _leftPanel.add(_changeDrawingButton);
        String toRegEx = "Switch to RegEx";
        String toDrawing = "Switch to Drawing";
        _leftSwitchButton = new JButton(toRegEx);
        _leftSwitchButtonListener = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (_regexSelected) {
                    //we now load a Drawing
                    _leftSwitchButton.setText(toRegEx);
                    _leftPanel.remove(0);
                    _leftPanel.add(new JLabel("No Drawing selected!"), 0);
                    _leftPanel.add(_changeDrawingButton, 1);
                } else {
                    //we now enter a RegEx
                    _leftSwitchButton.setText(toDrawing);
                    _leftPanel.remove(0);
                    _leftPanel.remove(0);
                    _regexInputField = new JTextField();
                    _regexInputField.setHorizontalAlignment(JTextField.HORIZONTAL);
                    _leftPanel.add(_regexInputField, 0);
                }
                _regexSelected = !_regexSelected;
            }
        };
        _leftSwitchButton.addActionListener(_leftSwitchButtonListener);
        _leftPanel.add(_leftSwitchButton);

        /*------------ create center ------------*/
        JPanel centerPanel = new JPanel();
        centerPanel.setLayout(new BoxLayout(centerPanel, BoxLayout.Y_AXIS));
        _compareButton = new JButton("Compare");
        _compareButtonListener = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                if (_regexSelected) {
                    String input = _regexInputField.getText().replace(" ", "");
                    try {
                        FASyntaxChecker.checkNFAWordSyntax(input);
                    } catch (Exception ex) {
                        ex.printStackTrace();
                        return;
                    }
                    _leftDrawing =
                        (FADrawing) FAHelper.convertModelToDrawing(FAHelper.regexToNfa(input));
                    //DrawPlugin.getGui().openDrawing(_leftDrawing); //debug statement
                }
                for (FADrawing rightDrawing : _rightDrawings) {
                    String[] separatingWord =
                        AutomataComparator.nfaLanguageEquivalence(_leftDrawing, rightDrawing);
                    String suffix = "Equal!";
                    if (separatingWord != null) {
                        if (separatingWord[1].equals("")) {
                            separatingWord[1] = "epsilon";
                        }
                        String notAcceptedBy = rightDrawing.getName();
                        if (separatingWord[0].equals(notAcceptedBy)) {
                            notAcceptedBy = "Template";
                        }
                        suffix = "Not Equal!\n    " + separatingWord[0] + " accepts \""
                            + separatingWord[1] + "\"\n    But " + notAcceptedBy + " does not!";
                    }
                    System.out.println("Comparing " + rightDrawing.getName() + " : " + suffix);
                }
            }
        };
        _compareButton.addActionListener(_compareButtonListener);
        centerPanel.add(_compareButton);

        /*------------ create right side ------------*/
        JPanel rightPanel = new JPanel();
        rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.Y_AXIS));
        _addButtonRight = new JButton("Add Drawing");
        _addRightButtonListener = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JFileChooser chooser = new JFileChooser(System.getProperty("user.dir"));
                chooser.setFileFilter(
                    IOHelper.mapToSwingFileFilter(
                        DrawingTypeManager.getInstance().getFilter(FAPlugin.FA_FILEFILTER)));
                chooser.setAcceptAllFileFilterUsed(false);
                chooser.setMultiSelectionEnabled(true);
                int success = chooser.showOpenDialog(null);
                if (success != JFileChooser.APPROVE_OPTION) {
                    return;
                }
                File[] files = chooser.getSelectedFiles();
                for (File f : files) {
                    FADrawing faDrawing = (FADrawing) DrawingFileHelper.loadDrawing(f, message -> {
                    });
                    _rightDrawings.add(faDrawing);
                    JLabel newName = new JLabel(f.getName());
                    newName.setHorizontalAlignment(JLabel.HORIZONTAL);
                    rightPanel.add(newName, rightPanel.getComponentCount() - 1);
                }
                _frame.revalidate();
                _frame.pack();
                _frame.repaint();
            }
        };
        _addButtonRight.addActionListener(_addRightButtonListener);
        JPanel buttonPanel = new JPanel();
        buttonPanel.add(_addButtonRight);
        _removeAllButton = new JButton("Remove All");
        _removeAllButtonListener = new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                for (int i = rightPanel.getComponentCount() - 2; i > -1; i--) { //we start at -2, since the buttons are at -1
                    rightPanel.remove(i);
                }
                _rightDrawings.clear();
                _frame.revalidate();
                _frame.pack();
                _frame.repaint();
            }
        };
        _removeAllButton.addActionListener(_removeAllButtonListener);
        buttonPanel.add(_removeAllButton);
        rightPanel.add(buttonPanel);//if layout of rightPanel is changed, the ActionListener connected to the removeAll-button needs to be updated

        mainPanel.add(_leftPanel);
        mainPanel.add(centerPanel);
        mainPanel.add(rightPanel);
        _frame.add(mainPanel);
    }

    public void showGui() {
        _frame.setVisible(true);
        _frame.setState(java.awt.Frame.NORMAL);
        _frame.pack();
        _frame.setVisible(true);
    }

    public void cleanup() {

        _changeDrawingButton.removeActionListener(_changeDrawingButtonListener);
        _leftSwitchButton.removeActionListener(_leftSwitchButtonListener);
        _compareButton.removeActionListener(_compareButtonListener);
        _addButtonRight.removeActionListener(_addRightButtonListener);
        _removeAllButton.removeActionListener(_removeAllButtonListener);

        SwingUtilities.invokeLater(_frame::dispose);

    }

}
