package net.agspace;

import javax.swing.*;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;
import javax.swing.filechooser.FileFilter;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.io.*;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.List;

public class Window {

    //List of files that can be imported.
    private static final List<String> OPEN_FILE_EXTENSIONS = new ArrayList<>();

    static {
        OPEN_FILE_EXTENSIONS.add("txt");
    }

    private JPanel mainPanel;
    private JPanel tengwarPanel;
    private JPanel tengwarPanelTop;
    private JLabel tengwarPanelLabel;
    private JTextArea tengwarTextArea;
    private JPanel inputPanel;
    private JPanel inputPanelTop;
    private JLabel inputPanelLabel;
    private JTextArea inputTextArea;
    private JPanel translateButtonPanel;
    private JButton toTengwarButton;
    private JButton toEnglishButton;
    private JButton clearButton;

    private boolean isLive = false;

    Window() {
        //Load the font into the system.
        $$$setupUI$$$();
        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
        try {
            ge.registerFont(Font.createFont(Font.TRUETYPE_FONT, this.getClass().getClassLoader().getResourceAsStream("tngan.ttf")));
        } catch (FontFormatException e) {
            System.err.println("Font format exception!");
        } catch (IOException e) {
            System.err.println("IOException!");
        }

        //Explicit translation from english to tengwar.
        toTengwarButton.addActionListener(e -> tengwarTextArea.setText(Translator.translateToTengwar(inputTextArea.getText())));

        //Clear both text areas.
        clearButton.addActionListener(e -> {
            tengwarTextArea.setText(null);
            inputTextArea.setText(null);
        });

        //Translate tengwar to english.
        toEnglishButton.addActionListener(e -> inputTextArea.setText(Translator.translateToEnglish(tengwarTextArea.getText())));
    }

    private void createUIComponents() {
        mainPanel = new JPanel();
        this.inputTextArea = new JTextArea();
        inputTextArea.getDocument().addDocumentListener(new DocumentListener() {
            @Override
            public void insertUpdate(DocumentEvent e) {
                onEnglishTextChanged();
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                onEnglishTextChanged();
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
                onEnglishTextChanged();
            }
        });
        this.tengwarTextArea = new JTextArea();
        tengwarTextArea.getDocument().addDocumentListener(new DocumentListener() {
            @Override
            public void insertUpdate(DocumentEvent e) {
                onTengwarTextChanged();
            }

            @Override
            public void removeUpdate(DocumentEvent e) {
                onTengwarTextChanged();
            }

            @Override
            public void changedUpdate(DocumentEvent e) {
                onTengwarTextChanged();
            }
        });
        this.toTengwarButton = new JButton();
        this.toEnglishButton = new JButton();
        this.clearButton = new JButton();
        this.inputTextArea.requestFocus();
    }

    JPanel getMainPanel() {
        return this.mainPanel;
    }

    /**
     * If the english text is changed, and live is selected, then update the tengwar text.
     */
    private void onEnglishTextChanged() {
        if (isLive && inputTextArea.hasFocus())
            tengwarTextArea.setText(Translator.translateToTengwar(inputTextArea.getText()));
    }

    /**
     * If tengwar text is changed, and live is selected, then update the english text.
     */
    private void onTengwarTextChanged() {
        if (isLive && tengwarTextArea.hasFocus())
            inputTextArea.setText(Translator.translateToEnglish(tengwarTextArea.getText()));
    }

    /**
     * Toggle the live button and disable translate buttons if needed.
     *
     * @param e event generated by the check box.
     */
    void onLiveToggled(ActionEvent e) {
        if (((JCheckBoxMenuItem) e.getSource()).getState()) {
            //Deactivate buttons, set live to true.
            toTengwarButton.setEnabled(false);
            toEnglishButton.setEnabled(false);
            isLive = true;
        } else {
            //Activate buttons, set live to false.
            toTengwarButton.setEnabled(true);
            toEnglishButton.setEnabled(true);
            isLive = false;
        }
    }

    /**
     * What to do if the user clicks the 'import' button.
     */
    void onImportClicked() {
        JFileChooser fileChooser = new JFileChooser(System.getProperty("user.documents"));
        fileChooser.setFileFilter(new FileFilter() {
            @Override
            public boolean accept(File f) {
                if (f.isDirectory())
                    return true;
                String extension = Utils.getExtension(f);
                return extension != null && OPEN_FILE_EXTENSIONS.contains(extension.toLowerCase());
            }

            @Override
            public String getDescription() {
                return "Plain text files.";
            }
        });
        int result = fileChooser.showOpenDialog(this.mainPanel);
        if (result == JFileChooser.APPROVE_OPTION) {
            try (BufferedReader br = new BufferedReader(new FileReader(fileChooser.getSelectedFile()))) {
                StringBuilder sb = new StringBuilder();
                String line = br.readLine();
                while (line != null) {
                    sb.append(line);
                    sb.append(System.lineSeparator());
                    line = br.readLine();
                }
                inputTextArea.setText(sb.toString());
                tengwarTextArea.setText(Translator.translateToTengwar(inputTextArea.getText()));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * What to do when the user wants to save their document.
     */
    void onSaveClicked() {
        JFileChooser fileChooser = new JFileChooser(System.getProperty("user.documents"));
        int result = fileChooser.showSaveDialog(this.mainPanel);
        if (result == JFileChooser.APPROVE_OPTION) {
            try (PrintStream ps = new PrintStream(fileChooser.getSelectedFile())) {
                ps.println(tengwarTextArea.getText());
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * Attempt to open the pdf in the browser.
     */
    void onEnglishModeAboutClicked() {
        if (Desktop.isDesktopSupported()) {
            try {
                Desktop.getDesktop().browse(new URI("https://github.com/andrewlalis/TengwarTranslator/blob/master/src/resources/EnglishOneToOneTengwarV2-1.pdf"));
            } catch (URISyntaxException | IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * Attempt to open Tengwar wikipedia page.
     */
    void onTengwarAboutClicked() {
        if (Desktop.isDesktopSupported()) {
            try {
                Desktop.getDesktop().browse(new URI("https://en.wikipedia.org/wiki/Tengwar"));
            } catch (URISyntaxException | IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * Attempt to open my github page.
     */
    void onAboutMeClicked() {
        if (Desktop.isDesktopSupported()) {
            try {
                Desktop.getDesktop().browse(new URI("https://github.com/andrewlalis"));
            } catch (URISyntaxException | IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * @noinspection ALL
     */
    private Font $$$getFont$$$(String fontName, int style, int size, Font currentFont) {
        if (currentFont == null) return null;
        String resultName;
        if (fontName == null) {
            resultName = currentFont.getName();
        } else {
            Font testFont = new Font(fontName, Font.PLAIN, 10);
            if (testFont.canDisplay('a') && testFont.canDisplay('1')) {
                resultName = fontName;
            } else {
                resultName = currentFont.getName();
            }
        }
        return new Font(resultName, style >= 0 ? style : currentFont.getStyle(), size >= 0 ? size : currentFont.getSize());
    }

    /**
     * Method generated by IntelliJ IDEA GUI Designer
     * >>> IMPORTANT!! <<<
     * DO NOT edit this method OR call it in your code!
     *
     * @noinspection ALL
     */
    private void $$$setupUI$$$() {
        createUIComponents();
        mainPanel.setLayout(new GridBagLayout());
        mainPanel.setPreferredSize(new Dimension(720, 480));
        tengwarPanel = new JPanel();
        tengwarPanel.setLayout(new GridBagLayout());
        GridBagConstraints gbc;
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.weightx = 1.0;
        gbc.weighty = 1.0;
        gbc.fill = GridBagConstraints.BOTH;
        mainPanel.add(tengwarPanel, gbc);
        tengwarPanelTop = new JPanel();
        tengwarPanelTop.setLayout(new GridBagLayout());
        tengwarPanelTop.setPreferredSize(new Dimension(54, 30));
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.weightx = 1.0;
        gbc.fill = GridBagConstraints.BOTH;
        tengwarPanel.add(tengwarPanelTop, gbc);
        tengwarPanelLabel = new JLabel();
        Font tengwarPanelLabelFont = this.$$$getFont$$$("Tengwar Annatar", Font.PLAIN, 18, tengwarPanelLabel.getFont());
        if (tengwarPanelLabelFont != null) tengwarPanelLabel.setFont(tengwarPanelLabelFont);
        tengwarPanelLabel.setText("1b$y6D");
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.weightx = 1.0;
        gbc.weighty = 1.0;
        tengwarPanelTop.add(tengwarPanelLabel, gbc);
        final JScrollPane scrollPane1 = new JScrollPane();
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.weightx = 1.0;
        gbc.weighty = 1.0;
        gbc.fill = GridBagConstraints.BOTH;
        tengwarPanel.add(scrollPane1, gbc);
        Font tengwarTextAreaFont = this.$$$getFont$$$("Tengwar Annatar", Font.PLAIN, 16, tengwarTextArea.getFont());
        if (tengwarTextAreaFont != null) tengwarTextArea.setFont(tengwarTextAreaFont);
        tengwarTextArea.setLineWrap(true);
        tengwarTextArea.setWrapStyleWord(true);
        scrollPane1.setViewportView(tengwarTextArea);
        inputPanel = new JPanel();
        inputPanel.setLayout(new GridBagLayout());
        inputPanel.setEnabled(true);
        inputPanel.setVisible(true);
        gbc = new GridBagConstraints();
        gbc.gridx = 2;
        gbc.gridy = 0;
        gbc.weightx = 1.0;
        gbc.weighty = 1.0;
        gbc.fill = GridBagConstraints.BOTH;
        mainPanel.add(inputPanel, gbc);
        inputPanelTop = new JPanel();
        inputPanelTop.setLayout(new GridBagLayout());
        inputPanelTop.setEnabled(true);
        Font inputPanelTopFont = this.$$$getFont$$$(null, -1, -1, inputPanelTop.getFont());
        if (inputPanelTopFont != null) inputPanelTop.setFont(inputPanelTopFont);
        inputPanelTop.setPreferredSize(new Dimension(56, 30));
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.weightx = 1.0;
        gbc.fill = GridBagConstraints.BOTH;
        inputPanel.add(inputPanelTop, gbc);
        inputPanelLabel = new JLabel();
        Font inputPanelLabelFont = this.$$$getFont$$$(null, Font.PLAIN, 18, inputPanelLabel.getFont());
        if (inputPanelLabelFont != null) inputPanelLabel.setFont(inputPanelLabelFont);
        inputPanelLabel.setText("English");
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.weightx = 1.0;
        gbc.weighty = 1.0;
        inputPanelTop.add(inputPanelLabel, gbc);
        final JScrollPane scrollPane2 = new JScrollPane();
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.weightx = 1.0;
        gbc.weighty = 1.0;
        gbc.fill = GridBagConstraints.BOTH;
        inputPanel.add(scrollPane2, gbc);
        inputTextArea.setEditable(true);
        inputTextArea.setLineWrap(true);
        inputTextArea.setWrapStyleWord(true);
        scrollPane2.setViewportView(inputTextArea);
        translateButtonPanel = new JPanel();
        translateButtonPanel.setLayout(new GridBagLayout());
        gbc = new GridBagConstraints();
        gbc.gridx = 1;
        gbc.gridy = 0;
        gbc.weighty = 1.0;
        gbc.anchor = GridBagConstraints.NORTH;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        gbc.insets = new Insets(50, 0, 0, 0);
        mainPanel.add(translateButtonPanel, gbc);
        toTengwarButton.setIcon(new ImageIcon(getClass().getResource("/toTengwar.png")));
        toTengwarButton.setLabel("");
        toTengwarButton.setText("");
        toTengwarButton.setToolTipText("Translate to tengwar");
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 0;
        gbc.weightx = 1.0;
        gbc.weighty = 1.0;
        gbc.anchor = GridBagConstraints.SOUTH;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        translateButtonPanel.add(toTengwarButton, gbc);
        toEnglishButton.setIcon(new ImageIcon(getClass().getResource("/toEnglish.png")));
        toEnglishButton.setLabel("");
        toEnglishButton.setText("");
        toEnglishButton.setToolTipText("Translate to english");
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 1;
        gbc.weightx = 1.0;
        gbc.weighty = 1.0;
        gbc.anchor = GridBagConstraints.NORTH;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        translateButtonPanel.add(toEnglishButton, gbc);
        clearButton.setIcon(new ImageIcon(getClass().getResource("/clear.png")));
        clearButton.setLabel("");
        clearButton.setText("");
        gbc = new GridBagConstraints();
        gbc.gridx = 0;
        gbc.gridy = 2;
        gbc.weightx = 1.0;
        gbc.weighty = 1.0;
        gbc.fill = GridBagConstraints.HORIZONTAL;
        translateButtonPanel.add(clearButton, gbc);
        tengwarPanelLabel.setLabelFor(tengwarTextArea);
        inputPanelLabel.setLabelFor(inputTextArea);
    }

    /**
     * @noinspection ALL
     */
    public JComponent $$$getRootComponent$$$() {
        return mainPanel;
    }
}