/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.log4j.chainsaw;

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.log4j.chainsaw.helper.SwingHelper;
import org.apache.log4j.chainsaw.osx.OSXIntegration;

import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreeModel;
import java.awt.*;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Locale;
import org.apache.commons.configuration2.AbstractConfiguration;
import org.apache.log4j.chainsaw.prefs.SettingsManager;


/**
 * A panel used by the user to modify any application-wide preferences.
 *
 * @author Paul Smith &lt;psmith@apache.org&gt;
 */
public class ApplicationPreferenceModelPanel extends AbstractPreferencePanel {
    private static final Logger logger = LogManager.getLogger();
    
    private JTextField identifierExpression;
    private JTextField toolTipDisplayMillis;
    private JTextField cyclicBufferSize;
    private JComboBox<String> configurationURL;
    private GeneralAllPrefPanel generalAllPrefPanel;

    ApplicationPreferenceModelPanel() {
        initComponents();
        getOkButton().addActionListener(
            e -> {
                SettingsManager.getInstance().saveGlobalSettings();
                hidePanel();
            });

        getCancelButton().addActionListener(
            e -> {
                hidePanel();
            });
    }

    public void updateModel(){

    }

    /* (non-Javadoc)
     * @see org.apache.log4j.chainsaw.AbstractPreferencePanel#createTreeModel()
     */
    protected TreeModel createTreeModel() {
        final DefaultMutableTreeNode rootNode =
            new DefaultMutableTreeNode("Preferences");
        DefaultTreeModel model = new DefaultTreeModel(rootNode);

        generalAllPrefPanel = new GeneralAllPrefPanel();
        DefaultMutableTreeNode general =
            new DefaultMutableTreeNode(generalAllPrefPanel);

        DefaultMutableTreeNode visuals =
            new DefaultMutableTreeNode(new VisualsPrefPanel());

        rootNode.add(general);
        rootNode.add(visuals);

        return model;
    }

    public class VisualsPrefPanel extends BasicPrefPanel {
        private final JRadioButton topPlacement = new JRadioButton(" Top         ");
        private final JRadioButton bottomPlacement = new JRadioButton(" Bottom         ");
        private final JCheckBox statusBar = new JCheckBox(" Show Status bar ");
        private final JCheckBox toolBar = new JCheckBox(" Show Toolbar ");
        private final JCheckBox receivers = new JCheckBox(" Show Receivers ");
        private UIManager.LookAndFeelInfo[] lookAndFeels = UIManager.getInstalledLookAndFeels();
        private final ButtonGroup lookAndFeelGroup = new ButtonGroup();

        private VisualsPrefPanel() {
            super("Visuals");

            //Nimbus has major issues with colors in tables..just remove it from the list..
            //only use this if nimbus was found..
            UIManager.LookAndFeelInfo[] newLookAndFeels = new UIManager.LookAndFeelInfo[lookAndFeels.length];
            boolean useNewLookAndFeels = false;
            int j = 0;
            for (UIManager.LookAndFeelInfo lookAndFeel : lookAndFeels) {
                if (lookAndFeel.getClassName().toLowerCase(Locale.ENGLISH).contains("nimbus")) {
                    useNewLookAndFeels = true;
                } else {
                    newLookAndFeels[j++] = lookAndFeel;
                }
            }
            if (useNewLookAndFeels) {
                UIManager.LookAndFeelInfo[] replacedLookAndFeels = new UIManager.LookAndFeelInfo[lookAndFeels.length - 1];
                System.arraycopy(newLookAndFeels, 0, replacedLookAndFeels, 0, newLookAndFeels.length - 1);
                lookAndFeels = replacedLookAndFeels;
            }

            setupComponents();
            setupListeners();
            updateModel();
        }

        /**
         *
         */
        private void setupListeners() {
            final AbstractConfiguration config = SettingsManager.getInstance().getGlobalConfiguration();

            topPlacement.addActionListener(
                e -> config.setProperty("tabPlacement", SwingConstants.TOP));
            bottomPlacement.addActionListener(
                e -> config.setProperty("tabPlacement", SwingConstants.BOTTOM));

            statusBar.addActionListener(
                e -> config.setProperty("statusBar",statusBar.isSelected()));

            toolBar.addActionListener(
                e -> config.setProperty("toolbar",toolBar.isSelected()));

            receivers.addActionListener(
                e -> config.setProperty("showReceivers",receivers.isSelected()));

//            uncommittedPreferenceModel.addPropertyChangeListener(
//                "tabPlacement",
//                evt -> {
//                    int value = (Integer) evt.getNewValue();
//
//                    configureTabPlacement(value);
//                });
//
//            uncommittedPreferenceModel.addPropertyChangeListener(
//                "statusBar",
//                evt -> statusBar.setSelected(
//                    (Boolean) evt.getNewValue()));
//
//            uncommittedPreferenceModel.addPropertyChangeListener(
//                "toolbar",
//                evt -> toolBar.setSelected((Boolean) evt.getNewValue()));
//
//            uncommittedPreferenceModel.addPropertyChangeListener(
//                "receivers",
//                evt -> receivers.setSelected(
//                    (Boolean) evt.getNewValue()));
//
//            uncommittedPreferenceModel.addPropertyChangeListener(
//                "lookAndFeelClassName",
//                evt -> {
//                    String lf = evt.getNewValue().toString();
//
//                    Enumeration enumeration = lookAndFeelGroup.getElements();
//
//                    while (enumeration.hasMoreElements()) {
//                        JRadioButton button = (JRadioButton) enumeration.nextElement();
//
//                        if (button.getName() != null && button.getName().equals(lf)) {
//                            button.setSelected(true);
//
//                            break;
//                        }
//                    }
//                });
        }

        /**
         *
         */
        private void setupComponents() {
            setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

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

            tabPlacementBox.setBorder(BorderFactory.createTitledBorder(" Tab Placement "));

            ButtonGroup tabPlacementGroup = new ButtonGroup();

            tabPlacementGroup.add(topPlacement);
            tabPlacementGroup.add(bottomPlacement);

            tabPlacementBox.add(topPlacement);
            tabPlacementBox.add(bottomPlacement);

            /**
             * If we're OSX, we're 'not allowed' to change the tab placement...
             */
            if (OSXIntegration.IS_OSX) {
                tabPlacementBox.setEnabled(false);
                topPlacement.setEnabled(false);
                bottomPlacement.setEnabled(false);
            }

            add(tabPlacementBox);
            add(statusBar);
            add(receivers);
            add(toolBar);

            JPanel lfPanel = new JPanel();
            lfPanel.setLayout(new BoxLayout(lfPanel, BoxLayout.Y_AXIS));
            lfPanel.setBorder(BorderFactory.createTitledBorder(" Look & Feel "));
            final AbstractConfiguration configuration = SettingsManager.getInstance().getGlobalConfiguration();

            for (final UIManager.LookAndFeelInfo lfInfo : lookAndFeels) {
                final JRadioButton lfItem = new JRadioButton(" " + lfInfo.getName() + " ");
                lfItem.setName(lfInfo.getClassName());
                lfItem.addActionListener(
                    e -> configuration.setProperty("lookAndFeelClassName",
                        lfInfo.getClassName()));
                lookAndFeelGroup.add(lfItem);
                lfPanel.add(lfItem);
            }

            try {
                final Class gtkLF =
                    Class.forName("com.sun.java.swing.plaf.gtk.GTKLookAndFeel");
                final JRadioButton lfIGTK = new JRadioButton(" GTK+ 2.0 ");
                lfIGTK.addActionListener(
                    e -> configuration.setProperty("lookAndFeelClassName",
                        gtkLF.getName()));
                lookAndFeelGroup.add(lfIGTK);
                lfPanel.add(lfIGTK);
            } catch (Exception e) {
                logger.debug("Can't find new GTK L&F, might be Windows, or <JDK1.4.2");
            }

            add(lfPanel);

            add(
                new JLabel(
                    "<html>Look and Feel change will apply the next time you start Chainsaw.<br>" +
                        "If this value is not set, the default L&F of your system is used.</html>"));
        }

        private void configureTabPlacement(int value) {
            switch (value) {
                case SwingConstants.TOP:
                    topPlacement.setSelected(true);

                    break;

                case SwingConstants.BOTTOM:
                    bottomPlacement.setSelected(true);

                    break;

                default:
                    break;
            }
        }

        public void updateModel(){
            AbstractConfiguration config = SettingsManager.getInstance().getGlobalConfiguration();

            statusBar.setSelected(config.getBoolean("statusBar"));
            receivers.setSelected(config.getBoolean("showReceivers"));
            toolBar.setSelected(config.getBoolean("toolbar"));
            configureTabPlacement(config.getInt("tabPlacement"));
            Enumeration e = lookAndFeelGroup.getElements();
            while (e.hasMoreElements()) {
                JRadioButton radioButton = (JRadioButton) e.nextElement();
                if (radioButton.getText().equals(config.getString("lookAndFeelClassName"))) {
                    radioButton.setSelected(true);
                    break;
                }
            }
        }
    }

    /**
     * @author psmith
     */
    public class GeneralAllPrefPanel extends BasicPrefPanel {
        private final JCheckBox showNoReceiverWarning =
            new JCheckBox(" Prompt me on startup if there are no Receivers defined ");
        private final JCheckBox showSplash = new JCheckBox(" Show Splash screen at startup ");
        private final JSlider responsiveSlider =
            new JSlider(SwingConstants.HORIZONTAL, 1, 4, 2);
        private final JCheckBox confirmExit = new JCheckBox(" Confirm Exit ");
        Dictionary<Integer, JLabel> sliderLabelMap = new Hashtable<>();

        private final JCheckBox okToRemoveSecurityManager = new JCheckBox(" Ok to remove SecurityManager ");

        public GeneralAllPrefPanel() {
            super("General");

            GeneralAllPrefPanel.this.initComponents();
        }

        private void initComponents() {
            setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));

            configurationURL = new JComboBox(); //new JComboBox<>(new DefaultComboBoxModel<>(committedPreferenceModel.getConfigurationURLs()));
            configurationURL.setEditable(true);
            configurationURL.setPrototypeDisplayValue("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
            configurationURL.setPreferredSize(new Dimension(375, 13));

            identifierExpression = new JTextField(30);
            toolTipDisplayMillis = new JTextField(8);
            cyclicBufferSize = new JTextField(8);
            Box p = new Box(BoxLayout.X_AXIS);

            p.add(showNoReceiverWarning);
            p.add(Box.createHorizontalGlue());

            confirmExit.setToolTipText("If set, you prompt to confirm Chainsaw exit");
            okToRemoveSecurityManager.setToolTipText("You will need to tick this to be able to load Receivers/Plugins that require external dependancies.");
            setupInitialValues();
            setupListeners();

            initSliderComponent();
            add(responsiveSlider);

            JPanel p1 = new JPanel(new FlowLayout(FlowLayout.LEFT));

            p1.add(new JLabel(" Tab name/event routing expression "));
            p1.add(Box.createHorizontalStrut(5));
            p1.add(identifierExpression);
            add(p1);
            add(p);

            Box p2 = new Box(BoxLayout.X_AXIS);
            p2.add(confirmExit);
            p2.add(Box.createHorizontalGlue());

            Box p3 = new Box(BoxLayout.X_AXIS);
            p3.add(showSplash);
            p3.add(Box.createHorizontalGlue());

            Box ok4 = new Box(BoxLayout.X_AXIS);
            ok4.add(okToRemoveSecurityManager);
            ok4.add(Box.createHorizontalGlue());

            add(p2);
            add(p3);
            add(ok4);

            JPanel p4 = new JPanel(new FlowLayout(FlowLayout.LEFT));

            p4.add(new JLabel(" ToolTip Display (millis) "));
            p4.add(Box.createHorizontalStrut(5));
            p4.add(toolTipDisplayMillis);
            add(p4);

            JPanel p5 = new JPanel(new FlowLayout(FlowLayout.LEFT));

            p5.add(new JLabel(" Cyclic buffer size "));
            p5.add(Box.createHorizontalStrut(5));
            p5.add(cyclicBufferSize);
            p5.add(Box.createHorizontalStrut(5));
            p5.add(new JLabel(" (effective on restart) "));
            add(p5);

            Box p6 = new Box(BoxLayout.Y_AXIS);

            Box configURLPanel = new Box(BoxLayout.X_AXIS);
            JLabel configLabel = new JLabel(" Auto Config URL ");
            configURLPanel.add(configLabel);
            configURLPanel.add(Box.createHorizontalStrut(5));

            configURLPanel.add(configurationURL);
            configURLPanel.add(Box.createHorizontalGlue());

            p6.add(configURLPanel);

            JButton browseButton = new JButton(" Open File... ");
//            browseButton.addActionListener(e -> browseForConfiguration());
            Box browsePanel = new Box(BoxLayout.X_AXIS);
            browsePanel.add(Box.createHorizontalGlue());
            browsePanel.add(browseButton);
            p6.add(Box.createVerticalStrut(5));
            p6.add(browsePanel);
            p6.add(Box.createVerticalGlue());
            add(p6);

            configurationURL.setToolTipText("A complete and valid URL identifying the location of a valid log4 xml configuration file to auto-configure Receivers and other Plugins");
            configurationURL.setInputVerifier(new InputVerifier() {

                public boolean verify(JComponent input) {
                    try {
                        String selectedItem = (String) configurationURL.getSelectedItem();
                        if (selectedItem != null && !(selectedItem.trim().equals(""))) {
                            new URL(selectedItem);
                        }
                    } catch (Exception e) {
                        return false;
                    }
                    return true;
                }
            });
//            String configToDisplay = committedPreferenceModel.getBypassConfigurationURL() != null ? committedPreferenceModel.getBypassConfigurationURL() : committedPreferenceModel.getConfigurationURL();
//            configurationURL.setSelectedItem(configToDisplay);
        }

//        public void browseForConfiguration() {
//            String defaultPath = ".";
//            if (configurationURL.getItemCount() > 0) {
//                Object selectedItem = configurationURL.getSelectedItem();
//                if (selectedItem != null) {
//                    File currentConfigurationPath = new File(selectedItem.toString()).getParentFile();
//                    if (currentConfigurationPath != null) {
//                        defaultPath = currentConfigurationPath.getPath();
//                        //FileDialog will not navigate to this location unless we remove the prefixing protocol and slash
//                        //at least on winxp
//                        if (defaultPath.toLowerCase(Locale.ENGLISH).startsWith("file:\\")) {
//                            defaultPath = defaultPath.substring("file:\\".length());
//                        }
//                    }
//                }
//            }
//            File selectedFile = SwingHelper.promptForFile(this, defaultPath, "Select a Chainsaw configuration file", true);
//            if (selectedFile != null) {
//                try {
//                    String newConfigurationFile = selectedFile.toURI().toURL().toExternalForm();
//                    if (!committedPreferenceModel.getConfigurationURLs().contains(newConfigurationFile)) {
//                        configurationURL.addItem(newConfigurationFile);
//                    }
//                    configurationURL.setSelectedItem(newConfigurationFile);
//                } catch (MalformedURLException e1) {
//                    e1.printStackTrace();
//                }
//            }
//        }

        private void initSliderComponent() {
            responsiveSlider.setToolTipText(
                "Adjust to set the responsiveness of the app.  How often the view is updated.");
            responsiveSlider.setSnapToTicks(true);
            responsiveSlider.setLabelTable(sliderLabelMap);
            responsiveSlider.setPaintLabels(true);
            responsiveSlider.setPaintTrack(true);

            responsiveSlider.setBorder(BorderFactory.createTitledBorder(" Responsiveness "));

            //            responsiveSlider.setAlignmentY(0);
            //            responsiveSlider.setAlignmentX(0);
        }

        private void setupListeners() {
//            uncommittedPreferenceModel.addPropertyChangeListener(
//                "showNoReceiverWarning",
//                evt -> showNoReceiverWarning.setSelected(
//                    (Boolean) evt.getNewValue()));
//
//            uncommittedPreferenceModel.addPropertyChangeListener("showSplash", evt -> {
//                boolean value = (Boolean) evt.getNewValue();
//                showSplash.setSelected(value);
//            });
//
//            uncommittedPreferenceModel.addPropertyChangeListener("okToRemoveSecurityManager", evt -> {
//                boolean newValue = (Boolean) evt.getNewValue();
//                if (newValue) {
//                    okToRemoveSecurityManager.setSelected(newValue);
//                } else {
//                    okToRemoveSecurityManager.setSelected(false);
//                }
//
//            });
//
//
//            uncommittedPreferenceModel.addPropertyChangeListener(
//                "identifierExpression",
//                evt -> identifierExpression.setText(evt.getNewValue().toString()));
//
//            uncommittedPreferenceModel.addPropertyChangeListener(
//                "responsiveness",
//                evt -> {
//                    int value = (Integer) evt.getNewValue();
//
//                    if (value >= 1000) {
//                        int newValue = (value - 750) / 1000;
//                        logger.debug(
//                            "Adjusting old Responsiveness value from " + value + " to "
//                                + newValue);
//                        value = newValue;
//                    }
//
//                    responsiveSlider.setValue(value);
//                });
//
//            uncommittedPreferenceModel.addPropertyChangeListener(
//                "toolTipDisplayMillis",
//                evt -> toolTipDisplayMillis.setText(evt.getNewValue().toString()));
//
//            uncommittedPreferenceModel.addPropertyChangeListener(
//                "cyclicBufferSize",
//                evt -> cyclicBufferSize.setText(evt.getNewValue().toString()));
//
//            showNoReceiverWarning.addActionListener(
//                e -> uncommittedPreferenceModel.setShowNoReceiverWarning(
//                    showNoReceiverWarning.isSelected()));
//
//            showSplash.addActionListener(e -> uncommittedPreferenceModel.setShowSplash(showSplash.isSelected()));
//
//            okToRemoveSecurityManager.addActionListener(e -> {
//
//                if (okToRemoveSecurityManager.isSelected() && JOptionPane.showConfirmDialog(okToRemoveSecurityManager, "By ticking this option, you are authorizing Chainsaw to remove Java's Security Manager.\n\n" +
//                    "This is required under Java Web Start so that it can access Jars/classes locally.  Without this, Receivers like JMSReceiver + DBReceiver that require" +
//                    " specific driver jars will NOT be able to be run.  \n\n" +
//                    "By ticking this, you are saying that this is ok.", "Please Confirm", JOptionPane.YES_NO_OPTION) == JOptionPane.YES_OPTION) {
//                    uncommittedPreferenceModel.setOkToRemoveSecurityManager(true);
//                } else {
//                    uncommittedPreferenceModel.setOkToRemoveSecurityManager(false);
//                }
//
//            });
//
//
//            responsiveSlider.getModel().addChangeListener(
//                e -> {
//                    if (responsiveSlider.getValueIsAdjusting()) {
//                        /**
//                         * We'll wait until it stops.
//                         */
//                    } else {
//                        int value = responsiveSlider.getValue();
//
//                        if (value == 0) {
//                            value = 1;
//                        }
//
//                        logger.debug("Adjust responsiveness to " + value);
//                        uncommittedPreferenceModel.setResponsiveness(value);
//                    }
//                });
//
//            uncommittedPreferenceModel.addPropertyChangeListener(
//                "confirmExit",
//                evt -> {
//                    boolean value = (Boolean) evt.getNewValue();
//                    confirmExit.setSelected(value);
//                });
//
//            uncommittedPreferenceModel.addPropertyChangeListener("configurationURL", evt -> {
//                String value = evt.getNewValue().toString();
//                configurationURL.setSelectedItem(value);
//            });
//            confirmExit.addActionListener(
//                e -> uncommittedPreferenceModel.setConfirmExit(
//                    confirmExit.isSelected()));
        }

        private void setupInitialValues() {
            sliderLabelMap.put(1, new JLabel(" Fastest "));
            sliderLabelMap.put(2, new JLabel(" Fast "));
            sliderLabelMap.put(3, new JLabel(" Medium "));
            sliderLabelMap.put(4, new JLabel(" Slow "));

            //
//            showNoReceiverWarning.setSelected(
//                uncommittedPreferenceModel.isShowNoReceiverWarning());
//            identifierExpression.setText(
//                uncommittedPreferenceModel.getIdentifierExpression());
//
//            confirmExit.setSelected(uncommittedPreferenceModel.isConfirmExit());
//            okToRemoveSecurityManager.setSelected(uncommittedPreferenceModel.isOkToRemoveSecurityManager());
//            showNoReceiverWarning.setSelected(uncommittedPreferenceModel.isShowNoReceiverWarning());
//            showSplash.setSelected(uncommittedPreferenceModel.isShowSplash());
//            identifierExpression.setText(uncommittedPreferenceModel.getIdentifierExpression());
//            toolTipDisplayMillis.setText(uncommittedPreferenceModel.getToolTipDisplayMillis() + "");
//            cyclicBufferSize.setText(uncommittedPreferenceModel.getCyclicBufferSize() + "");
//            configurationURL.setSelectedItem(uncommittedPreferenceModel.getConfigurationURL());
        }
    }
}
