/*   **********************************************************************  **
 **   Copyright notice                                                       **
 **                                                                          **
 **   (c) 2003-2006 RSSOwl Development Team                                  **
 **   http://www.rssowl.org/                                                 **
 **                                                                          **
 **   All rights reserved                                                    **
 **                                                                          **
 **   This program and the accompanying materials are made available under   **
 **   the terms of the Eclipse Public License 1.0 which accompanies this     **
 **   distribution, and is available at:                                     **
 **   http://www.rssowl.org/legal/epl-v10.html                               **
 **                                                                          **
 **   A copy is found in the file epl-v10.html and important notices to the  **
 **   license from the team is found in the textfile LICENSE.txt distributed **
 **   in this package.                                                       **
 **                                                                          **
 **   This copyright notice MUST APPEAR in all copies of the file!           **
 **                                                                          **
 **   Contributors:                                                          **
 **     RSSOwl - initial API and implementation (bpasero@rssowl.org)         **
 **                                                                          **
 **  **********************************************************************  */

package net.sourceforge.rssowl.controller.properties;

import net.sourceforge.rssowl.controller.GUI;
import net.sourceforge.rssowl.util.GlobalSettings;
import net.sourceforge.rssowl.util.i18n.Dictionary;
import net.sourceforge.rssowl.util.shop.FontShop;
import net.sourceforge.rssowl.util.shop.HotkeyShop;
import net.sourceforge.rssowl.util.shop.LayoutShop;
import net.sourceforge.rssowl.util.shop.PaintShop;
import net.sourceforge.rssowl.util.shop.ProxyShop;
import net.sourceforge.rssowl.util.shop.WidgetShop;

import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CLabel;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Font;
import org.eclipse.swt.graphics.FontMetrics;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;

/**
 * A property page holds components to set properties in RSSOwl. It holds an
 * apply button to save the made changes and a restore defaults button to
 * restore the default settings.
 * 
 * @author <a href="mailto:bpasero@rssowl.org">Benjamin Pasero </a>
 * @version 1.2.3
 */
public abstract class PropertyPage {

  /** The PropertyChangeManager holds a temp state of the made settings */
  protected static PropertyChangeManager propertyChangeManager;

  /** Apply button */
  protected Button apply;

  /** Holds the Property Page */
  protected Composite composite;

  /** Font to use for the components */
  protected Font dialogFont = FontShop.dialogFont;

  /** Label to display a warning or warning */
  protected CLabel errorMessageLabel;

  /** Parent of the composite */
  protected Composite parent;

  /** Restore button */
  protected Button restore;

  /** GUI to access some methods */
  protected GUI rssOwlGui;

  /**
   * Instantiates a new PropertyPage
   * 
   * @param parent Composite's parent
   */
  protected PropertyPage(Composite parent) {
    this(parent, null);
  }

  /**
   * Instantiates a new PropertyPage
   * 
   * @param parent Composite's parent
   * @param rssOwlGui To access some methods
   */
  protected PropertyPage(Composite parent, GUI rssOwlGui) {
    this.parent = parent;
    this.rssOwlGui = rssOwlGui;
    createComposite();
    initComponents();
    createButtons();
  }

  /**
   * @return Returns the propertyChangeManager.
   */
  public static PropertyChangeManager getPropertyChangeManager() {
    return propertyChangeManager;
  }

  /**
   * Init the PropertyChangeManager's settings with the ones from GlobalSettings
   * 
   * @param rssOwlGui The MainController
   */
  public static void initPropertyChangeManager(GUI rssOwlGui) {
    propertyChangeManager = new PropertyChangeManager(rssOwlGui);
    propertyChangeManager.setAutoOpenEmptyNews(GlobalSettings.directOpenNews);
    propertyChangeManager.setAutoOpenEachNews(GlobalSettings.directOpenEachNews);
    propertyChangeManager.setCheckForUpdate(GlobalSettings.checkUpdate);
    propertyChangeManager.setCustomBrowserPath(GlobalSettings.customBrowser);
    propertyChangeManager.setCustomBrowserArguments(GlobalSettings.customBrowserArguments);
    propertyChangeManager.setDoubleClickOpen(GlobalSettings.isDoubleClickOpen);
    propertyChangeManager.setReopenFeeds(GlobalSettings.reopenFeeds);
    propertyChangeManager.setFocusNewTabs(GlobalSettings.focusNewTabs);

    if (GlobalSettings.useInternalBrowser()) {
      propertyChangeManager.setOpenBrowserExtern(GlobalSettings.openBrowserExtern);
      propertyChangeManager.setOpenBrowserInNewTab(GlobalSettings.openNewBrowserWindow);
      propertyChangeManager.setUseBrowserForNewsText(GlobalSettings.useBrowserForNewsText);
      propertyChangeManager.setBlockPopups(GlobalSettings.blockPopups);
    }

    propertyChangeManager.setThreeColumnGUI(GlobalSettings.isThreeColumnGUI);
    propertyChangeManager.setShowChannelInfo(GlobalSettings.showChannelInfo);

    if (GlobalSettings.useSystemTray())
      propertyChangeManager.setShowSystrayIcon(GlobalSettings.showSystrayIcon);

    propertyChangeManager.setProxySettings(ProxyShop.proxySettings);

    if (ProxyShop.isProxyProtected())
      propertyChangeManager.setUseAuthentification(true);

    propertyChangeManager.setSelectedEncoding(GlobalSettings.charEncoding);
    propertyChangeManager.setSortOrder(GlobalSettings.sortOrder);
    propertyChangeManager.setAutoSortNews(GlobalSettings.autoSortNews);
    propertyChangeManager.setSelectedLanguage(Dictionary.selectedLanguage);
    propertyChangeManager.setMailBody(GlobalSettings.mailBody);
    propertyChangeManager.setMailSubject(GlobalSettings.mailSubject);
    propertyChangeManager.setDialogFont(FontShop.dialogFont);
    propertyChangeManager.setTreeFont(FontShop.treeFont);
    propertyChangeManager.setTableFont(FontShop.tableFont);
    propertyChangeManager.setTextFont(FontShop.textFont);
    propertyChangeManager.setHeaderFont(FontShop.headerFont);
    propertyChangeManager.setMaxConnectionCount(GlobalSettings.maxConnectionCount);
    propertyChangeManager.setConnectionTimeout(GlobalSettings.connectionTimeout);
    propertyChangeManager.setHtmlFormatMail(GlobalSettings.htmlFormatMail);
    propertyChangeManager.setHotkeys(HotkeyShop.hotKeys);
    propertyChangeManager.setLocalCacheFeeds(GlobalSettings.localCacheFeeds);
    propertyChangeManager.setLinkColor(GlobalSettings.linkColor);
    propertyChangeManager.setSimpleTabs(GlobalSettings.simpleTabs);
    propertyChangeManager.setShowTabCloseButton(GlobalSettings.showTabCloseButton);
    propertyChangeManager.setDisplaySingleTab(GlobalSettings.displaySingleTab);
    propertyChangeManager.setSyntaxHighlightColor(GlobalSettings.syntaxHighlightColor);
    propertyChangeManager.setBloggerArguments(GlobalSettings.bloggerArguments);
    propertyChangeManager.setBloggerPath(GlobalSettings.bloggerPath);
    propertyChangeManager.setTrayOnStartup(GlobalSettings.trayOnStartup);
    propertyChangeManager.setTrayOnExit(GlobalSettings.trayOnExit);
    propertyChangeManager.setConfirmFavoriteDeletion(GlobalSettings.confirmFavoriteDeletion);
    propertyChangeManager.setConfirmCategoryDeletion(GlobalSettings.confirmCategoryDeletion);
    propertyChangeManager.setConfirmBlogrollDeletion(GlobalSettings.confirmBlogrollDeletion);
    propertyChangeManager.setShowErrors(GlobalSettings.showErrors);
    propertyChangeManager.setMarkAllReadOnMinimize(GlobalSettings.markAllReadOnMinimize);
    propertyChangeManager.setShowTrayPopup(GlobalSettings.showTrayPopup);
    propertyChangeManager.setUpdateProxyForAllFavorites(GlobalSettings.setProxyForAllFavorites);
    propertyChangeManager.setMarkFeedReadOnTabClose(GlobalSettings.markFeedReadOnTabClose);
    propertyChangeManager.setAutoCloseNewsPopup(GlobalSettings.autoCloseNewsPopup);
    propertyChangeManager.setAnimateNewsPopup(GlobalSettings.animateNewsPopup);
    propertyChangeManager.setFavDefaultAutoReloadInterval(GlobalSettings.favDefaultAutoReloadInterval);
    propertyChangeManager.setFavDefaultOpenOnStartup(GlobalSettings.favDefaultOpenOnStartup);
    propertyChangeManager.setFavDefaultReloadOnStartup(GlobalSettings.favDefaultReloadOnStartup);
  }

  /** The apply button has been pressed */
  public abstract void applyButtonPressed();

  /** Dispose the composite that holds the property page */
  public void dispose() {
    composite.dispose();
  }

  /** Update the temporary settings holder PropertiesChangeManager */
  public abstract void updatePropertiesChangeManager();

  /** Create "Apply" and "Restore Defaults" button */
  protected void createButtons() {

    /** GridData for the buttonHolder */
    GridData gridData = new GridData(GridData.HORIZONTAL_ALIGN_END | GridData.VERTICAL_ALIGN_END);
    gridData.grabExcessVerticalSpace = true;
    gridData.grabExcessHorizontalSpace = true;
    gridData.horizontalSpan = 2;

    /** Composite holds the two buttons */
    Composite buttonHolder = new Composite(composite, SWT.NONE);
    buttonHolder.setLayoutData(gridData);
    buttonHolder.setLayout(LayoutShop.createGridLayout(2, 0, 0));

    /** A button to restore the default settings */
    restore = new Button(buttonHolder, SWT.NONE);
    restore.setText(GUI.i18n.getTranslation("BUTTON_RESTORE_DEFAULTS"));
    restore.setFont(dialogFont);
    restore.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(SelectionEvent e) {
        restoreButtonPressed();
      }
    });

    /** A button to save the made changes */
    apply = new Button(buttonHolder, SWT.NONE);
    apply.setText(GUI.i18n.getTranslation("BUTTON_APPLY"));
    apply.setFont(dialogFont);
    apply.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(SelectionEvent e) {
        applyButtonPressed();
      }
    });

    /** Set Layout Data to buttons */
    setButtonLayoutData(restore);
    setButtonLayoutData(apply);

    /** Set Mnemonics to Buttons */
    WidgetShop.initMnemonics(new Button[] { restore, apply });
  }

  /** Create the composite that holds the PropertyPage */
  protected void createComposite() {
    composite = new Composite(parent, SWT.NONE);
    composite.setLayout(LayoutShop.createGridLayout(2, 5, 5, 10));
    composite.setLayoutData(new GridData(GridData.VERTICAL_ALIGN_BEGINNING | GridData.FILL_BOTH));
  }

  /** Init all components */
  protected abstract void initComponents();

  /** The restore button has been pressed */
  protected abstract void restoreButtonPressed();

  /**
   * Enable / Disable the "Apply"-Button
   * 
   * @param enabled TRUE for enabled
   */
  protected void setApplyButtonState(boolean enabled) {
    apply.setEnabled(enabled);
  }

  /**
   * Set the layout data of the button to a GridData with appropriate heights
   * and widths.
   * 
   * @param button The button to set the layoutdata
   */
  protected void setButtonLayoutData(Button button) {
    setButtonLayoutData(button, new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING));
  }

  /**
   * Set the layout data of the button to a GridData with appropriate heights
   * and widths.
   * 
   * @param button The button to set the layoutdata
   * @param data The GridData to use
   */
  protected void setButtonLayoutData(Button button, GridData data) {

    /** GC to retrieve fontmetrics object */
    GC gc = new GC(button);
    FontMetrics fontMetrics = gc.getFontMetrics();

    /** Apply appropiate gridata */
    int widthHint = Dialog.convertHorizontalDLUsToPixels(fontMetrics, IDialogConstants.BUTTON_WIDTH);
    data.widthHint = Math.max(widthHint, button.computeSize(SWT.DEFAULT, SWT.DEFAULT, true).x);
    button.setLayoutData(data);

    /** Dispose GC */
    gc.dispose();
  }

  /**
   * Set / unset the error message on the dialog
   * 
   * @param errorMessage The warning message or NULL for no warning
   */
  protected void setErrorMessage(String errorMessage) {
    errorMessageLabel.setImage(errorMessage == null ? null : PaintShop.iconError);
    errorMessageLabel.setText(errorMessage == null ? "" : errorMessage);
    errorMessageLabel.getParent().layout();
  }

  /**
   * Enable / Disable the "Restore"-Button
   * 
   * @param enabled TRUE for enabled
   */
  protected void setRestoreButtonState(boolean enabled) {
    restore.setEnabled(enabled);
  }

  /**
   * Set / unset the success message on the dialog
   * 
   * @param successMessage The success message or NULL for no warning
   */
  protected void setSuccessMessage(String successMessage) {
    errorMessageLabel.setImage(successMessage == null ? null : PaintShop.iconValidate);
    errorMessageLabel.setText(successMessage == null ? "" : successMessage);
    errorMessageLabel.getParent().layout();
  }

  /**
   * Set / unset the warning message on the dialog
   * 
   * @param warningMessage The warning message or NULL for no warning
   */
  protected void setWarningMessage(String warningMessage) {
    errorMessageLabel.setImage(warningMessage == null ? null : PaintShop.iconWarning);
    errorMessageLabel.setText(warningMessage == null ? "" : warningMessage);
    errorMessageLabel.getParent().layout();
  }
}