/*
 * $Id$
 *
 * Copyright 1996-2008 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */
package com.sun.javatest.tool;

import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Enumeration;
import java.util.Map;
import javax.swing.plaf.basic.BasicComboBoxRenderer;
import javax.swing.Box;
import javax.swing.ButtonGroup;
import javax.swing.ButtonModel;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JRadioButton;

/**
 * Preferences for the desktop itself.
 */
class DesktopPrefsPane extends Preferences.Pane {
    DesktopPrefsPane(Desktop desktop, UIFactory uif) {
        this.desktop = desktop;
        this.uif = uif;
        setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        c.fill = GridBagConstraints.HORIZONTAL;
        c.gridwidth = GridBagConstraints.REMAINDER;
        c.weightx = 1;
        c.insets.bottom= 10; // set off subsequent entries

        add(createDesktopStylePanel(), c);
        add(createToolTipsPanel(), c);
        add(createShutdownPanel(), c);

        c.fill = GridBagConstraints.BOTH;
        c.weighty = 1;
        add(Box.createVerticalGlue(), c);
    }

    public String getText() {
        return uif.getI18NString("dt.prefs.name");
    }

    public void load(Map m) {
        String styleName = (String) (m.get(Desktop.STYLE_PREF));
        if (styleName == null)
            styleName = Desktop.styleNames[desktop.getStyle()];

        for (Enumeration e = styleGrp.getElements(); e.hasMoreElements(); ) {
            JRadioButton rb = (JRadioButton)e.nextElement();
            if (rb.getActionCommand().equals(styleName)) {
                rb.setSelected(true);
                break;
            }
        }
        // tooltips
        String tipState = (String) (m.get(Desktop.TTIP_PREF));
        ttipsCheck.setSelected(tipState == null || tipState.equalsIgnoreCase("true"));

        boolean complete = false;       // used for delay and duration code

        String tipDelay = (String) (m.get(Desktop.TTIP_DELAY));
        try {
            int delay = Integer.parseInt(tipDelay);

            if (delay == Desktop.TTIP_DELAY_NONE) {
                // no delay
                ttDelay.setSelectedItem(tooltipDelays[0]);
                complete = true;
            }
            else {
                for (int i = 1; i < ttDelay.getItemCount(); i++) {
                    if ( ((Integer)(ttDelay.getItemAt(i))).intValue() == delay ) {
                        ttDelay.setSelectedIndex(i);
                        i = ttDelay.getItemCount(); // stop loop
                        complete = true;
                    }
                }   // for

            }   // if/else
        }
        catch (NumberFormatException e) {
            complete = false;
        }

        ttDelay.setEnabled(ttipsCheck.isSelected());
        ttDuration.setEnabled(ttipsCheck.isSelected());

        // default
        if (!complete)
                ttDelay.setSelectedIndex(1);

        complete = false;
        String tipDuration = (String) (m.get(Desktop.TTIP_DURATION));
        try {
            int duration = Integer.parseInt(tipDuration);
            if (duration == Desktop.TTIP_DURATION_FOREVER) {
                // forever
                ttDuration.setSelectedItem(tooltipDurations[tooltipDurations.length-1]);
                complete = true;
            }
            else {
                for (int i = 0; i < tooltipDurations.length-1; i++) {
                    if (duration == tooltipDurations[i].intValue()) {
                        ttDuration.setSelectedItem(tooltipDurations[i]);
                        complete = true;
                        i = tooltipDurations.length;    // stop loop
                    }
                }   // for
            }   // if/else
        }   // try
        catch (NumberFormatException e) {
            complete = false;
        }   // catch

        // default
        if (!complete){
                ttDuration.setSelectedItem(tooltipDurations[1]);
            }

        // make it happen
        syncTooltipPrefs();

        // save on exit
        String saveState = (String) (m.get(Desktop.SAVE_ON_EXIT_PREF));
        saveCheck.setSelected(saveState == null || saveState.equalsIgnoreCase("true"));
    }

    public void save(Map m) {
        ButtonModel bm = styleGrp.getSelection();
        if (bm != null) {
            String styleName = bm.getActionCommand();
            for (int i = 0; i < Desktop.styleNames.length; i++) {
                if (styleName.equals(Desktop.styleNames[i])) {
                    desktop.setStyle(i);
                    m.put(Desktop.STYLE_PREF, styleName);
                    break;
                }
            }
        }

        boolean tips = ttipsCheck.isSelected();
        m.put(Desktop.TTIP_PREF, String.valueOf(tips));
        desktop.setTooltipsEnabled(tips);

        int delay = getTooltipDelay();
        m.put(Desktop.TTIP_DELAY, Integer.toString(delay));
        desktop.setTooltipDelay(delay);

        int duration = getTooltipDuration();
        m.put(Desktop.TTIP_DURATION, Integer.toString(duration));
        desktop.setTooltipDuration(duration);

        m.put(Desktop.SAVE_ON_EXIT_PREF, String.valueOf(saveCheck.isSelected()));
        desktop.setSaveOnExit(saveCheck.isSelected());

        syncTooltipPrefs();
    }

    /**
     * Force the GUI and the actual settings to be synchronized.
     */
    private void syncTooltipPrefs() {
        boolean tips = ttipsCheck.isSelected();
        desktop.setTooltipsEnabled(tips);

        int delay = getTooltipDelay();
        desktop.setTooltipDelay(delay);

        int duration = getTooltipDuration();
        desktop.setTooltipDuration(duration);
    }

    private Component createDesktopStylePanel() {
        Box p = Box.createHorizontalBox();
        p.setBorder(uif.createTitledBorder("dt.prefs.style"));
        styleGrp = new ButtonGroup();
        for (int i = 0; i < Desktop.styleNames.length; i++) {
            String styleName = Desktop.styleNames[i];
            String uiKey = "dt.prefs." + styleName;
            JRadioButton b = uif.createRadioButton(uiKey, styleGrp);
            b.setActionCommand(styleName);
            p.add(b);
        }
        p.add(Box.createHorizontalGlue());

        return p;
    }

    private Component createShutdownPanel() {
        Box p = Box.createHorizontalBox();
        p.setBorder(uif.createTitledBorder("dt.prefs.shutdown"));
        saveCheck = uif.createCheckBox("dt.prefs.saveOnExit");
        p.add(saveCheck);
        p.add(Box.createHorizontalGlue());
        return p;
    }

    private Component createToolTipsPanel() {
        JPanel p = uif.createPanel("dt.prefs.tt", false);

        p.setLayout(new GridBagLayout());
        GridBagConstraints c = new GridBagConstraints();
        c.anchor = GridBagConstraints.WEST;
        c.ipadx = 3;
        c.ipady = 5;
        c.fill = GridBagConstraints.VERTICAL;
        c.insets.left = 3;
        c.insets.right = 3;
        c.insets.top = 2;
        c.insets.bottom = 2;

        p.setBorder(uif.createTitledBorder("dt.prefs.ttips"));
        ttipsCheck = uif.createCheckBox("dt.prefs.ttips");
        // override default name
        uif.setAccessibleName(ttipsCheck, "dt.prefs.ttips");

        ttipsCheck.addActionListener(new ActionListener() {
                public void actionPerformed(ActionEvent e) {
                    boolean state = ttipsCheck.isSelected();
                    ttDelay.setEnabled(state);
                    ttDuration.setEnabled(state);
                }
            });
        c.gridwidth = GridBagConstraints.REMAINDER;
        c.weightx = 1;
        p.add(ttipsCheck, c);

        loadTooltipResources();

        JLabel l = uif.createLabel("dt.prefs.ttDelay", true);

        ttDelay = uif.createChoice("dt.prefs.ttDelay", l);
        for (int i = 0; i < tooltipDelays.length; i++)
            ttDelay.addItem(tooltipDelays[i]);

        ttDelay.setSelectedItem(tooltipDelays[0]);
        ttDelay.setRenderer(new TipDelayRenderer());

        c.gridwidth = 1;
        c.weightx = 0;
        p.add(l, c);

        c.gridwidth = GridBagConstraints.REMAINDER;
        c.weightx = 1;
        p.add(ttDelay, c);

        l = uif.createLabel("dt.prefs.ttDuration", true);

        ttDuration = uif.createChoice("dt.prefs.ttDuration", l);
        for (int i = 0; i < tooltipDurations.length; i++)
            ttDuration.addItem(tooltipDurations[i]);

        ttDuration.setRenderer(new TipDurationRenderer());
        // nominate a reasonable choice
        ttDuration.setSelectedItem(tooltipDurations[
                Math.max(tooltipDurations.length-2, 0)]);

        c.gridwidth = 1;
        c.weightx = 0;
        p.add(l, c);

        c.gridwidth = GridBagConstraints.REMAINDER;
        c.weightx = 1;
        p.add(ttDuration, c);

        return p;
    }

    private void loadTooltipResources() {
        tooltipDurations = new Integer[] { new Integer(1000),
                                           new Integer(2000),
                                           new Integer(3000),
                                           new Integer(5000),
                                           new Integer(10000),
                                           new Integer(15000),
                                           new Integer(-1) };

        tooltipDelays = new Integer[] { new Integer(0),
                                        new Integer(1000),
                                        new Integer(2000),
                                        new Integer(3000),
                                        new Integer(5000),
                                        new Integer(10000) };
    }

    /**
     * How long before a tooltip should be shown, as known by the GUI.
     * @return Zero for no delay, otherwise a delay in milliseconds.
     */
    private int getTooltipDelay() {
        Integer value = (Integer)(ttDelay.getSelectedItem());
        return value.intValue();
    }

    /**
     * How long tooltips should be shown, as known by the GUI.
     * @return <code>Desktop.TTIP_DURATION_FOREVER</code>, otherwise a duration in
     *         milliseconds.
     */
    private int getTooltipDuration() {
        int value = ((Integer) (ttDuration.getSelectedItem())).intValue();
        return (value < 0 ? Desktop.TTIP_DURATION_FOREVER : value);
    }

    private Desktop desktop;
    private UIFactory uif;
    private ButtonGroup styleGrp;
    private JCheckBox ttipsCheck;
    private JComboBox ttDelay;
    private JComboBox ttDuration;
    private JCheckBox saveCheck;

    private Integer[] tooltipDurations;
    private Integer[] tooltipDelays;

    // cache localized strings because renderers tend to run a lot
    private static String TIP_SHOW_FOREVER;

    private class TipDelayRenderer extends BasicComboBoxRenderer {
        public Component getListCellRendererComponent(JList list,
                                              Object value,
                                              int index,
                                              boolean isSelected,
                                              boolean cellHasFocus) {
            Object theVal;
            if (value instanceof Integer) {
                int val = ((Integer)value).intValue();
                // convert to seconds and create localized text
                theVal = uif.getI18NString("dt.prefs.ttDelay", new Integer(val/1000));
            }
            else {
                theVal = value;
            }

            return super.getListCellRendererComponent(
                list, theVal, index, isSelected, cellHasFocus);
        }
    }

    private class TipDurationRenderer extends BasicComboBoxRenderer {
        TipDurationRenderer() {
            synchronized (DesktopPrefsPane.this) {
                if (TIP_SHOW_FOREVER  == null)
                    TIP_SHOW_FOREVER =
                        uif.getI18NString("dt.prefs.ttDuration.forev");
            }
        }

        public Component getListCellRendererComponent(JList list,
                                              Object value,
                                              int index,
                                              boolean isSelected,
                                              boolean cellHasFocus) {
            Object theVal;
            if (value instanceof Integer) {
                int val = ((Integer)value).intValue();
                if (val > 0) {
                    // convert to seconds and create localized text
                    theVal = uif.getI18NString("dt.prefs.ttDuration.sec",
                                new Integer(val/1000));
                }
                else
                    theVal = TIP_SHOW_FOREVER;
            }
            else {
                theVal = value;
            }

            return super.getListCellRendererComponent(
                list, theVal, index, isSelected, cellHasFocus);
        }
    }
}
