// ============================================================================
// File:               $File$
//
// Project:
//
// Purpose:
//
// Author:             Rammi
//
// Copyright Notice:   (c) 2005  Rammi (rammi@caff.de)
//                     This code is in the public domain.
//                     Use at own risk.
//                     No guarantees given.
//
// Latest change:      $Date$
//
// History:	       $Log$
//=============================================================================
package de.caff.util.settings.swing;

import de.caff.gimmicks.swing.ResourcedAction;
import de.caff.i18n.I18n;
import de.caff.i18n.swing.RJButton;
import de.caff.i18n.swing.RJLabel;
import de.caff.i18n.swing.RJPanel;
import de.caff.util.debug.Debug;

import javax.swing.*;
import javax.swing.event.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.*;

/**
 *  An editor for URL lists.
 *  @author <a href="mailto:rammi@caff.de">Rammi</a>
 *  @version $Revision$
 */
class UrlListEditor
        extends AbstractBasicEditorProvider
{
  /** The property which is edited. */
  private final SwingUrlListPreferenceProperty property;
  /** The panel containing the editor widgets. */
  private JPanel panel;
  /** A list of strings. */
  private JList list;

  private DefaultListModel getModel()
  {
    return (DefaultListModel)list.getModel();
  }

  private Action add    = new ResourcedAction("tbAdd") {
    public void actionPerformed(ActionEvent e)
    {
      UrlDialog dialog;
      Component root = SwingUtilities.getRoot(panel);
      if (root instanceof Dialog) {
        dialog = new UrlDialog((Dialog)root, null);
      }
      else if (root instanceof Frame) {
        dialog = new UrlDialog((Frame)root, null);
      }
      else {
        dialog = new UrlDialog(null);
      }
      dialog.setVisible(true);
      String url = dialog.getUrl();
      if (url != null) {
        getModel().addElement(url);
      }
    }

    protected Object clone() throws CloneNotSupportedException
    {
      return super.clone();
    }
  };
  private Action delete = new ResourcedAction("tbDelete") {
    public void actionPerformed(ActionEvent e)
    {
      getModel().removeElementAt(list.getSelectedIndex());
    }

    protected Object clone() throws CloneNotSupportedException
    {
      return super.clone();
    }
  };
  private Action change = new ResourcedAction("tbChange") {
    public void actionPerformed(ActionEvent e)
    {
      UrlDialog dialog;
      Component root = SwingUtilities.getRoot(panel);
      if (root instanceof Dialog) {
        dialog = new UrlDialog((Dialog)root, list.getSelectedValue().toString());
      }
      else if (root instanceof Frame) {
        dialog = new UrlDialog((Frame)root, list.getSelectedValue().toString());
      }
      else {
        dialog = new UrlDialog(list.getSelectedValue().toString());
      }
      dialog.setVisible(true);
      String url = dialog.getUrl();
      if (url != null) {
        getModel().setElementAt(url, list.getSelectedIndex());
      }
    }

    protected Object clone() throws CloneNotSupportedException
    {
      return super.clone();
    }
  };
  private Action up     = new ResourcedAction("tbUp") {
    public void actionPerformed(ActionEvent e)
    {
      int index = list.getSelectedIndex();
      swap(index, index-1);
    }

    protected Object clone() throws CloneNotSupportedException
    {
      return super.clone();
    }
  };
  private Action down   = new ResourcedAction("tbDown") {
    public void actionPerformed(ActionEvent e)
    {
      int index = list.getSelectedIndex();
      swap(index, index+11);
    }

    protected Object clone() throws CloneNotSupportedException
    {
      return super.clone();
    }
  };

  /**
   *  Constructor.
   *  @param property edited property
   *  @param l        locale
   */
  public UrlListEditor(SwingUrlListPreferenceProperty property, Locale l)
  {
    super(property, l);
    this.property = property;

    panel = new JPanel(new BorderLayout());
    JToolBar buttons = new JToolBar(JToolBar.VERTICAL);
    buttons.setFloatable(false);
    buttons.add(add);
    buttons.add(delete);
    buttons.addSeparator();
    buttons.add(change);
    buttons.addSeparator();
    buttons.add(up);
    buttons.add(down);
    panel.add(buttons, BorderLayout.EAST);
    list = new JList(createListModel(property.getUrlList()));
    panel.add(new JScrollPane(list), BorderLayout.CENTER);

    list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
    list.addListSelectionListener(new ListSelectionListener() {
      public void valueChanged(ListSelectionEvent e)
      {
        enableButtons(e.getFirstIndex());
      }
    });

    enableButtons(list.getSelectedIndex());
  }

  private static DefaultListModel createListModel(Collection c)
  {
    DefaultListModel model = new DefaultListModel();
    for (Iterator iterator = c.iterator(); iterator.hasNext();) {
      model.addElement(iterator.next());
    }
    return model;
  }

  private void swap(int index1, int index2)
  {
    final DefaultListModel model = (DefaultListModel)list.getModel();
    Object obj1 = model.getElementAt(index1);
    Object obj2 = model.getElementAt(index2);
    model.setElementAt(obj1, index2);
    model.setElementAt(obj2, index1);
  }

  private void enableButtons(int index)
  {
    if (index < 0) {
      delete.setEnabled(false);
      change.setEnabled(false);
      up.setEnabled(false);
      down.setEnabled(false);
    }
    else {
      delete.setEnabled(true);
      change.setEnabled(true);
      up.setEnabled(index > 0);
      down.setEnabled(index < list.getModel().getSize()-1);
    }
  }

  /**
   * Get an component for editing .
   *
   * @return editor component
   */
  public JComponent getEditor()
  {
    return panel;
  }

  /**
   * Reset the value in the editor to the basic value.
   */
  public void reset()
  {
    final DefaultListModel model = (DefaultListModel)list.getModel();
    model.removeAllElements();
    for (Iterator iterator = property.getUrlList().iterator(); iterator.hasNext();) {
      model.addElement(iterator.next());
    }
  }

  /**
   * Set the basic value from the editor.
   */
  public void save()
  {
    final DefaultListModel model = (DefaultListModel)list.getModel();
    property.setUrlList(Arrays.asList(model.toArray()));
  }

  /**
   * Called when the editor provider is no longer used.
   */
  public void goodBye()
  {
  }

  /**
   *  Helper dialog for editing URLs.
   */
  private static class UrlDialog
          extends JDialog
  {
    /** The field displaying the URL. */
    private JTextField urlField;
    /** The okay button. */
    private JButton ok;
    /** The result. */
    private String result;

    /**
     * Constructor.
     * @param owner dialog owner
     * @param url   url to start with
     */
    UrlDialog(Dialog owner, String url)
    {
      super(owner);
      init(url);
      setLocationRelativeTo(owner);
    }

    /**
     * Constructor.
     * @param owner dialog owner
     * @param url   url to start with
     */
     UrlDialog(Frame owner, String url)
    {
      super(owner);
      init(url);
      setLocationRelativeTo(owner);
    }

    /**
     * Constructor.
     * @param url   url to start with
     */
     UrlDialog(String url)
    {
      init(url);
    }

    /**
     * Internally used to setup te dialog.
     * @param url  the URL to display
     */
    private void init(String url)
    {
      setModal(true);
      setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
      setTitle(I18n.getString("tiFontUrl"));
      urlField = new JTextField(url == null ? "" : url, 80);
      JButton urlButton = new RJButton("btFontUrl");
      JPanel panel = new RJPanel(new BorderLayout());
      panel.setBorder(BorderFactory.createCompoundBorder(BorderFactory.createEmptyBorder(8, 8, 8, 8),
                                                         BorderFactory.createEtchedBorder()));
      ok = new RJButton("Ok");
      JButton cancel = new RJButton("Cancel");
      Box buttons = Box.createHorizontalBox();

      getContentPane().setLayout(new BorderLayout());
      panel.add(new RJLabel("lbFontUrl"), BorderLayout.WEST);
      panel.add(urlField, BorderLayout.CENTER);
      panel.add(urlButton, BorderLayout.EAST);
      buttons.add(Box.createHorizontalGlue());
      buttons.add(ok);
      buttons.add(cancel);
      buttons.add(Box.createHorizontalGlue());
      getContentPane().add(panel,   BorderLayout.NORTH);
      getContentPane().add(buttons, BorderLayout.SOUTH);

      urlButton.addActionListener(new ActionListener()
      {
        public void actionPerformed(ActionEvent e)
        {
          JFileChooser chooser = new JFileChooser(urlField.getText());
          chooser.setMultiSelectionEnabled(false);
          chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
          int returnVal = chooser.showOpenDialog(UrlDialog.this);
          if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = chooser.getSelectedFile();
            if (file != null) {
              try {
                urlField.setText(file.toURL().toString());
              } catch (MalformedURLException x) {
                // how can this happen?
                Debug.error(x);
              }
            }
          }
        }
      });

      urlField.addCaretListener(new CaretListener()
      {
        public void caretUpdate(CaretEvent e)
        {
          checkUrl();
        }
      });

      ok.addActionListener(new ActionListener()
      {
        public void actionPerformed(ActionEvent e)
        {
          result = urlField.getText().trim();
          dispose();
        }
      });

      cancel.addActionListener(new ActionListener()
      {
        public void actionPerformed(ActionEvent e)
        {
          dispose();
        }
      });

      checkUrl();
      pack();
    }

    private void checkUrl()
    {
      String url = getUrl();
      try {
        new URL(url);
        ok.setEnabled(true);
        urlField.setBackground(Color.white);
      } catch (MalformedURLException x) {
        ok.setEnabled(false);
        urlField.setBackground(new Color(0xff, 0xc0, 0xc0));
      }
    }

    public String getUrl()
    {
      return result;
    }
  }
}
