package org.limewire.ui.swing.search;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.Box;
import javax.swing.Icon;
import javax.swing.JLabel;
import javax.swing.JPanel;

import net.miginfocom.swing.MigLayout;

import org.jdesktop.application.Resource;
import org.jdesktop.swingx.JXPanel;
import org.limewire.setting.evt.SettingEvent;
import org.limewire.setting.evt.SettingListener;
import org.limewire.ui.swing.components.ColoredBusyLabel;
import org.limewire.ui.swing.components.IconButton;
import org.limewire.ui.swing.settings.SwingUiSettings;
import org.limewire.ui.swing.util.GuiUtils;
import org.limewire.ui.swing.util.I18n;
import org.limewire.ui.swing.util.ResizeUtils;
import org.limewire.ui.swing.util.SwingUtils;

/**
 * A message panel that appears (sometimes) above the search results.
 * If the user tries to start a search before the application
 * has finished loading or before it has fully connected, the messages
 * "WireShare will start your search right after it finishes loading." and
 * "You might not receive many results until WireShare is fully connected."
 * will be shown here.  It also may show a hint to the user regarding how to 
 * switch to the classic search results view.
 */
class SearchResultsMessagePanel extends JXPanel implements SettingListener {
    
    /**
     * This enumeration indicates which type of message should be shown.
     * NONE shows no message at all.
     * CONNECTING_TO_ULTRAPEERS shows the message "You might not receive many results until WireShare is fully connected"
     * CLASSIC_SEARCH_RESULTS_HINT shows an arrow pointing to the button that switches to the classic table view of search results.
     */
    public enum MessageType {
        NONE,                       
        CONNECTING_TO_ULTRAPEERS,   
        CLASSIC_SEARCH_RESULTS_HINT 
    }
    
    // We will only show the classic search results hint panel if the user hasn't closed it in the past.
    // So, let's defer creating it until we're sure we need it.
    private ClassicSearchResultsHintPanel classicSearchResultsHintPanel;
    // We will only show the message panel if the user tries to search for something before LimeWire
    // has connected to all of its ultra peers. So, let's defer creating it until we're sure we need it.
    private MessagePanel messagePanel;
    
    private JPanel currentPanel = null;
    
    @Resource private int height;
    @Resource private Color background;
    @Resource private Font switchFont;
    @Resource private Color switchColor;
    @Resource private Font closeFont;
    @Resource private Icon switchArrowIcon;
    @Resource private Icon closeIcon;
    @Resource private Icon closeDownIcon;
    @Resource private Icon closeHoverIcon;
    
    public SearchResultsMessagePanel() {
        GuiUtils.assignResources(this);
        
        SwingUiSettings.SHOW_CLASSIC_REMINDER.addSettingListener(this);
        
        setLayout(new BorderLayout());
    }

    /**
     * This method updates the display of the message panel. The message panel can show
     * a connecting message, a hint for finding the classic search results
     * view, or nothing at all.
     * 
     * @param messageType - the type of message that should be shown
     */
    public void setMessageType(MessageType messageType) {
        switch (messageType) {
        case CONNECTING_TO_ULTRAPEERS:
            getMessagePanel().setMessage(I18n.tr("You might not receive many results until WireShare is fully connected"));
            installPanel(getMessagePanel());
            break;
            
        case CLASSIC_SEARCH_RESULTS_HINT:
            installPanel(getClassicSearchResultsHintPanel());
            break;
            
        case NONE:
            installPanel(null);
            break;
            
        default:
            throw new IllegalStateException("invalid type: " + messageType);                 
        }
    }
    
    /*
     * Remove the existing panel and use the given panel for the user interface
     */
    private void installPanel(JPanel panel) {
        if (currentPanel != panel) {
            removeAll();
            if (panel != null) {
                add(panel);
            }
            currentPanel = panel;
        }
        setVisible(currentPanel != null);
    }

    void dispose() {
        SwingUiSettings.SHOW_CLASSIC_REMINDER.removeSettingListener(this);
    }
    
    public boolean isShowClassicSearchResultsHint() {
        return SwingUiSettings.SHOW_CLASSIC_REMINDER.getValue();
    }

    @Override
    public void settingChanged(SettingEvent evt) {
        SwingUtils.invokeNowOrLater(new Runnable() {
            @Override
            public void run() {
                if (SwingUiSettings.SHOW_CLASSIC_REMINDER.getValue()) {
                    installPanel( getClassicSearchResultsHintPanel() );
                }
                setVisible(SwingUiSettings.SHOW_CLASSIC_REMINDER.getValue());
            }
        });
    }

    private ClassicSearchResultsHintPanel getClassicSearchResultsHintPanel() {
        if (classicSearchResultsHintPanel == null) {
            classicSearchResultsHintPanel = new ClassicSearchResultsHintPanel();
        }
        
        return classicSearchResultsHintPanel;
    }

    private MessagePanel getMessagePanel() {
        if (messagePanel == null) {
            messagePanel = new MessagePanel();
        }
        
        return messagePanel;
    }
   
    private class ClassicSearchResultsHintPanel extends JPanel {

        public ClassicSearchResultsHintPanel() {           
            super(new MigLayout("insets 0, gap 0, fill, aligny center"));
            ResizeUtils.forceHeight(this, height);
            setBackground(background);
            
            // button to close the classic search results hint
            IconButton close = new IconButton(new AbstractAction(I18n.tr("close"), closeIcon) {
                @Override
                public void actionPerformed(ActionEvent e) {
                    SwingUiSettings.SHOW_CLASSIC_REMINDER.setValue(false);
                    SearchResultsMessagePanel.this.setVisible(false);
                }
            });
            close.setPressedIcon(closeDownIcon);
            close.setRolloverIcon(closeHoverIcon);
            close.setFont(closeFont);
            add(close, "gapleft 8, push");
            
            JLabel hintLabel = new JLabel(I18n.tr("Switch to Classic View"));
            hintLabel.setFont(switchFont);
            hintLabel.setForeground(switchColor);
            add(hintLabel, "gapbefore 4, alignx right");

            // arrow icon that points at the classic search results button
            add(new JLabel(switchArrowIcon), "gapbefore 4, gapright 25, alignx right");
        }       
    }
    
    private class MessagePanel extends JPanel {
        private JLabel messageLabel;

        public MessagePanel() {
            super(new MigLayout("insets 0, gap 0, fill, aligny center"));
            ResizeUtils.forceHeight(this, height);
            setBackground(background);

            // the message should be right aligned. so, let's add a glue component to push the message
            // over as far right as possible.
            add(Box.createHorizontalGlue(), "gapbefore 4, alignx center, push");
                       
            // the message text should be set via the setMessage method
            messageLabel = new JLabel("");
            messageLabel.setFont(switchFont);
            messageLabel.setForeground(switchColor);
            add(messageLabel, "gapbefore 4, aligny center, alignx right");

            // a busy label showing that the application is still loading or connecting
            ColoredBusyLabel busyLabel = new ColoredBusyLabel(new Dimension(20, 20));
            busyLabel.setBusy(true);
            add(busyLabel, "gapbefore 25, gapright 25, alignx right");
        }
       
        void setMessage(String message) {
            messageLabel.setText(message);
        }
    } 
}
