/*
 * Copyright (c) 2002-2007 TeamDev Ltd. All rights reserved.
 *
 * Use is subject to license terms.
 *
 * The complete licence text can be found at
 * http://www.teamdev.com/winpack/license.jsf
 */
package com.jniwrapper.win32.ie.samples.demo.components;

import com.jniwrapper.util.FlagSet;

import javax.swing.*;
import javax.swing.border.EmptyBorder;
import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;

/**
 * This component represents functionality for choosing URLs.
 *
 * @author Serge Piletsky
 */
public class URLField extends JComboBox
{
    private static final ImageIcon DOCUMENT_ICON = new ImageIcon(URLField.class.getResource("res/doc.gif"));
    private static final String BLANK_PAGE = "about:blank";

    private Map _domain2IconMap = new HashMap();
    private URLComboBoxEditor _URLComboBoxEditor = new URLComboBoxEditor();

    public URLField()
    {
        _domain2IconMap.put("", DOCUMENT_ICON);

        setRenderer(new URLListCellRenderer());
        setEditor(_URLComboBoxEditor);
        setEditable(true);
        addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                final ImageIcon imageIcon = (ImageIcon)_domain2IconMap.get(getHost((String)getSelectedItem()));
                _URLComboBoxEditor._urlIcon.setIcon(imageIcon);
                _URLComboBoxEditor._editor.requestFocus();
            }
        });
    }

    public void setURLText(String url)
    {
        _URLComboBoxEditor._editor.setText(url);
        _URLComboBoxEditor.loadIcon(url);
    }

    public void setURL(String url)
    {
        if (url == null || url.length() == 0 || url.equals(BLANK_PAGE))
        {
            _URLComboBoxEditor._urlIcon.setIcon(DOCUMENT_ICON);
            _URLComboBoxEditor._editor.setText("");
            return;
        }
        setSelectedItem(url);
        _URLComboBoxEditor._editor.setText(url);

        SwingUtilities.invokeLater(new Runnable()
        {
            public void run()
            {
                _URLComboBoxEditor.loadFavoriteIcon();
            }
        });
    }

    private static String getHost(String url)
    {
        String result = "";
        try
        {
            result = new URL(url).getHost();
        }
        catch (MalformedURLException e)
        {
        }
        return result;
    }

    public void requestFocus()
    {
        _URLComboBoxEditor._editor.requestFocus();
    }

    public Object getSelectedItem()
    {
        final Object result = super.getSelectedItem();
        return result == null ? "" : result.toString();
    }

    private class URLComboBoxEditor extends JPanel implements ComboBoxEditor, ActionListener
    {
        private static final String HTTP_PROTOCOL = "http://";
        private static final String DEFAULT_URL_PATTERN = HTTP_PROTOCOL + "www.{0}.com";
        private JTextField _editor = new JTextField();
        private JLabel _urlIcon;
        private Object _oldValue;

        public URLComboBoxEditor()
        {
            setBorder(null);
            setLayout(new BorderLayout());
            setBackground(_editor.getBackground());

            _urlIcon = new JLabel(DOCUMENT_ICON);
            _urlIcon.setPreferredSize(new Dimension(20, 20));

            _editor.setBorder(null);
            _editor.addActionListener(this);
            _editor.addKeyListener(new KeyAdapter()
            {
                public void keyTyped(KeyEvent e)
                {
                    final String text = _editor.getText();
                    FlagSet modifiers = new FlagSet(e.getModifiersEx());
                    if (e.getKeyChar() == '\n')
                    {
                        if (modifiers.contains(KeyEvent.CTRL_DOWN_MASK))
                        {
                            final String newURL = MessageFormat.format(DEFAULT_URL_PATTERN, new Object[]{text});
                            _editor.setText(newURL);
                            _editor.postActionEvent();
                        }
                        else if (!text.toLowerCase().startsWith(HTTP_PROTOCOL))
                        {
                            _editor.setText(text);
                            _editor.postActionEvent();
                        }
                    }
                }
            });


            add(_urlIcon, BorderLayout.WEST);
            add(_editor, BorderLayout.CENTER);
        }

        public void actionPerformed(ActionEvent e)
        {
            loadFavoriteIcon();
        }

        private void loadFavoriteIcon()
        {
            String urlText = _editor.getText();
            String host = getHost(urlText);

            DefaultComboBoxModel model = (DefaultComboBoxModel)URLField.this.getModel();
            if (model.getIndexOf(urlText) == -1)
            {
                insertItemAt(urlText, 0);
                if (_domain2IconMap.containsKey(host))
                {
                    _urlIcon.setIcon((ImageIcon)_domain2IconMap.get(host));
                }
                else
                {
                    _urlIcon.setIcon(DOCUMENT_ICON);
                    loadIcon(urlText);
                }
            }
        }

        private void loadIcon(final String urlText)
        {
            Thread loadingThread = new Thread(new Runnable()
            {
                public void run()
                {
                    try
                    {
                        ImageIcon imageIcon = new ImageIcon(new FavoriteIcon(urlText).toImage());
                        _domain2IconMap.put(getHost(urlText), imageIcon);
                        _urlIcon.setIcon(imageIcon);
                    }
                    catch (Exception e)
                    {
                        _domain2IconMap.put(getHost(urlText), DOCUMENT_ICON);
                    }
                }
            });
            loadingThread.start();
        }

        public Component getEditorComponent()
        {
            return this;
        }

        public void setItem(Object anObject)
        {
            if (anObject != null)
            {
                _editor.setText(anObject.toString());
                _oldValue = anObject;
            }
            else
            {
                _editor.setText("");
            }
        }

        public Object getItem()
        {
            Object newValue = _editor.getText();
            if (_oldValue != null && !(_oldValue instanceof String))
            {
                if (newValue.equals(_oldValue.toString()))
                {
                    return _oldValue;
                }
                else
                {
                    Class cls = _oldValue.getClass();
                    try
                    {
                        Method method = cls.getMethod("valueOf", new Class[]{String.class});
                        newValue = method.invoke(_oldValue, new Object[]{_editor.getText()});
                    }
                    catch (Exception ex)
                    {
                    }
                }
            }
            return newValue;
        }

        public void selectAll()
        {
            _editor.selectAll();
            _editor.requestFocus();
        }

        public void addActionListener(ActionListener l)
        {
            _editor.addActionListener(l);
        }

        public void removeActionListener(ActionListener l)
        {
            _editor.removeActionListener(l);
        }
    }

    class URLListCellRenderer extends JPanel implements ListCellRenderer
    {
        private JLabel _urlIcon;

        public URLListCellRenderer()
        {
            setBorder(null);
            _urlIcon = new JLabel();
            _urlIcon.setBorder(new EmptyBorder(1, 4, 1, 0));
            setLayout(new BorderLayout());
            add(_urlIcon, BorderLayout.WEST);
        }

        public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus)
        {
            String text = value.toString();
            _urlIcon.setText(text);
            if (index != -1)
            {
                _urlIcon.setIcon((ImageIcon)_domain2IconMap.get(getHost(text)));
                if (isSelected)
                {
                    _urlIcon.setForeground(list.getSelectionForeground());
                    setBackground(list.getSelectionBackground());
                }
                else
                {
                    _urlIcon.setForeground(list.getForeground());
                    setBackground(list.getBackground());
                }
            }
            return this;
        }
    }
}
