/*   **********************************************************************  **
 **   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.panel;

import net.sourceforge.rssowl.controller.EventManager;
import net.sourceforge.rssowl.controller.GUI;
import net.sourceforge.rssowl.controller.MenuManager;
import net.sourceforge.rssowl.controller.ViewForm;
import net.sourceforge.rssowl.dao.NewsfeedFactoryException;
import net.sourceforge.rssowl.model.TabItemData;
import net.sourceforge.rssowl.util.GlobalSettings;
import net.sourceforge.rssowl.util.shop.FontShop;
import net.sourceforge.rssowl.util.shop.LayoutShop;
import net.sourceforge.rssowl.util.shop.PaintShop;
import net.sourceforge.rssowl.util.shop.StringShop;
import net.sourceforge.rssowl.util.shop.WidgetShop;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.MenuItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;

/**
 * The error panel is shown inside a CTabItem whenever an exception was thrown
 * while loading a newsfeed or after a failed import of an OPML file.
 * 
 * @author <a href="mailto:bpasero@rssowl.org">Benjamin Pasero </a>
 * @version 1.2.3
 */
public class ErrorPanel {
  private Display display;
  private Composite errorHolderAll;
  private Composite errorViewFormContent;
  private Composite parent;
  EventManager eventManager;
  NewsfeedFactoryException exception;
  GUI rssOwlGui;

  /**
   * Instantiate a new ErrorPanel
   * 
   * @param rssOwlGui The maincontroller
   * @param display The display
   * @param eventManager The eventmanager
   * @param parent The parent CTabFolder
   * @param exception The exception to show in the panel
   */
  public ErrorPanel(GUI rssOwlGui, Display display, EventManager eventManager, Composite parent, NewsfeedFactoryException exception) {
    this.rssOwlGui = rssOwlGui;
    this.display = display;
    this.eventManager = eventManager;
    this.parent = parent;
    this.exception = exception;
    initComponents();
    initPopupMenu();
  }

  /**
   * Get the Error Panel
   * 
   * @return Composite The error panel
   */
  public Composite getPanel() {
    return errorHolderAll;
  }

  /**
   * Init all Components
   */
  private void initComponents() {

    /** Composite containing all components */
    errorHolderAll = new Composite(parent, SWT.NONE);
    errorHolderAll.setLayout(LayoutShop.createGridLayout(1, 2, 2, true));
    errorHolderAll.setBackground(display.getSystemColor(SWT.COLOR_WHITE));

    /** ViewForm containing title, error message and buttons */
    ViewForm errorViewForm = new ViewForm(errorHolderAll, SWT.BORDER | SWT.FLAT);
    errorViewForm.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
    errorViewForm.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

    /** Composite containing the error title */
    Composite errorTitleHolder = new Composite(errorViewForm, SWT.NONE);
    errorTitleHolder.setBackground(PaintShop.grayViewFormColor);
    errorTitleHolder.setLayout(LayoutShop.createGridLayout(1, 0, 3));
    errorTitleHolder.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

    /** Apply label holder to ViewForm */
    errorViewForm.setTopLeft(errorTitleHolder, false);

    /** Error Title */
    Label errorTitle = new Label(errorTitleHolder, SWT.CENTER);
    errorTitle.setLayoutData(new GridData(SWT.CENTER, SWT.CENTER, true, false));
    errorTitle.setBackground(PaintShop.grayViewFormColor);
    errorTitle.setForeground(display.getSystemColor(SWT.COLOR_RED));
    errorTitle.setFont(FontShop.textBoldFont);

    /** Prepare Title */
    String title = "";
    if (exception.getTitle() != null)
      title = StringShop.printf(GUI.i18n.getTranslation("ERROR_LOADING_FEED"), new String[] { "%TITLE%" }, new String[] { exception.getTitle() });
    else
      title = StringShop.printf(GUI.i18n.getTranslation("ERROR_LOADING_FEED"), new String[] { "%TITLE%" }, new String[] { exception.getUrl() });

    /** Escape Ampersand */
    errorTitle.setText(StringShop.escapeAmpersands(title));

    /** Content Container */
    errorViewFormContent = new Composite(errorViewForm, SWT.NONE);
    errorViewFormContent.setLayout(LayoutShop.createGridLayout(1, 0, 0, false));
    errorViewFormContent.setBackground(display.getSystemColor(SWT.COLOR_WHITE));

    /** Composite holding the message */
    Composite messageHolder = new Composite(errorViewFormContent, SWT.NONE);
    messageHolder.setLayout(LayoutShop.createGridLayout(2, 10, 10, false));
    messageHolder.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, true, true));
    messageHolder.setBackground(display.getSystemColor(SWT.COLOR_WHITE));

    /** Error Message Value */
    Label errorMessageLabelValue = new Label(messageHolder, SWT.READ_ONLY | SWT.WRAP);
    errorMessageLabelValue.setFont(FontShop.textBoldFont);
    errorMessageLabelValue.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false, 2, 1));
    errorMessageLabelValue.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
    errorMessageLabelValue.setText(exception.getMsg() + "\n\n");

    /** Error Reason */
    if (exception.getReason() != null) {

      /** Label */
      Label errorSourceLabel = new Label(messageHolder, SWT.NONE);
      errorSourceLabel.setFont(FontShop.textBoldFont);
      errorSourceLabel.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false));
      errorSourceLabel.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
      errorSourceLabel.setText(GUI.i18n.getTranslation("ERROR_REASON") + ": ");

      /** Value */
      Text errorSourceLabelValue = new Text(messageHolder, SWT.READ_ONLY | SWT.WRAP);
      errorSourceLabelValue.setFont(FontShop.textFont);
      errorSourceLabelValue.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
      errorSourceLabelValue.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
      errorSourceLabelValue.setText(exception.getReason());
    }

    /** HTTP Status */
    if (exception.getHttpStatus() != null) {

      /** Label */
      Label errorHttpStatusLabel = new Label(messageHolder, SWT.NONE);
      errorHttpStatusLabel.setFont(FontShop.textBoldFont);
      errorHttpStatusLabel.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false));
      errorHttpStatusLabel.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
      errorHttpStatusLabel.setText(GUI.i18n.getTranslation("ERROR_HTTP_STATUS") + ": ");

      /** Value */
      Text errorHttpStatusLabelValue = new Text(messageHolder, SWT.READ_ONLY | SWT.WRAP);
      errorHttpStatusLabelValue.setFont(FontShop.textFont);
      errorHttpStatusLabelValue.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
      errorHttpStatusLabelValue.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
      errorHttpStatusLabelValue.setText(exception.getHttpStatus());
    }

    /** If working offline, offer a Button to go online */
    if (GlobalSettings.workOffline) {

      /** Spacer */
      new Label(messageHolder, SWT.NONE).setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false));

      /** Button for going Online */
      final Button goOnlineButton = new Button(messageHolder, SWT.PUSH);
      goOnlineButton.setText(GUI.i18n.getTranslation("MENU_WORK_ONLINE"));
      goOnlineButton.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
      goOnlineButton.setLayoutData(new GridData(SWT.BEGINNING, SWT.BEGINNING, false, false));

      /** Go online and reload the Feed */
      goOnlineButton.addSelectionListener(new SelectionAdapter() {
        public void widgetSelected(SelectionEvent e) {
          goOnlineButton.setEnabled(false);
          GlobalSettings.workOffline = false;
          rssOwlGui.getRSSOwlMenu().updateOfflineModeItem();
          eventManager.actionReload();
        }
      });
    }

    /** ViewForm Separator */
    ViewForm buttonHolderSeparator = new ViewForm(errorViewFormContent, SWT.BORDER | SWT.FLAT);
    buttonHolderSeparator.setOnlyBorderTop(true);
    buttonHolderSeparator.setLayoutData(new GridData(SWT.FILL, SWT.END, true, true));
    buttonHolderSeparator.setBackground(display.getSystemColor(SWT.COLOR_WHITE));
    buttonHolderSeparator.setBackground(PaintShop.grayViewFormColor);

    /** Container for the buttons */
    Composite buttonHolder = new Composite(buttonHolderSeparator, SWT.NONE);
    buttonHolder.setLayout(LayoutShop.createFillLayout(0, 0));
    buttonHolder.setBackground(PaintShop.grayViewFormColor);

    /** Apply Content */
    buttonHolderSeparator.setTopLeft(buttonHolder, false);

    /** ToolBar for Items */
    ToolBar buttonToolBar = new ToolBar(buttonHolder, SWT.FLAT);
    buttonToolBar.setFont(FontShop.dialogFont);
    buttonToolBar.setBackground(PaintShop.grayViewFormColor);

    /** Reload the Feed */
    ToolItem reloadItem = new ToolItem(buttonToolBar, SWT.PUSH);
    reloadItem.setText(GUI.i18n.getTranslation("MENU_RELOAD"));
    reloadItem.setImage(PaintShop.iconReload);
    reloadItem.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(SelectionEvent e) {
        eventManager.actionReload();
      }
    });

    /** Separator */
    new ToolItem(buttonToolBar, SWT.SEPARATOR);

    /** Validate the Feed */
    ToolItem validateItem = new ToolItem(buttonToolBar, SWT.PUSH);
    validateItem.setText(GUI.i18n.getTranslation("MENU_VALIDATE") + "...");
    validateItem.setImage(PaintShop.iconValidate);
    validateItem.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(SelectionEvent e) {
        eventManager.actionValidateFeeds(true);
      }
    });

    /** Separator */
    new ToolItem(buttonToolBar, SWT.SEPARATOR);

    /** Open Feed URL in Browser */
    ToolItem openUrlItem = new ToolItem(buttonToolBar, SWT.PUSH);
    openUrlItem.setText(GUI.i18n.getTranslation("BUTTON_OPEN_IN_BROWSER"));
    openUrlItem.setImage(PaintShop.iconWorld);
    openUrlItem.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(SelectionEvent e) {
        openFeedInBrowser();
      }
    });

    /** Init Menmonics on ToolItems */
    WidgetShop.initMnemonics(new ToolItem[] { reloadItem, validateItem, openUrlItem });

    /** Apply content */
    errorViewForm.setContent(errorViewFormContent, true);
  }

  /**
   * Initialize the Popup Menu
   */
  private void initPopupMenu() {

    /** Popup menuStructure for the label */
    Menu labelMenu = new Menu(errorViewFormContent);

    /** Add feed to favorites */
    MenuItem addFeedToFav = new MenuItem(labelMenu, SWT.NONE);
    rssOwlGui.getRSSOwlMenu().updateAccelerator(addFeedToFav, "BUTTON_ADDTO_FAVORITS", true, false);
    if (!GlobalSettings.isMac())
      addFeedToFav.setImage(PaintShop.iconAddToFavorites);
    addFeedToFav.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(SelectionEvent e) {
        eventManager.actionAddToFavorites();
      }
    });

    /** Separator */
    new MenuItem(labelMenu, SWT.SEPARATOR);

    MenuItem markUnreadItem = new MenuItem(labelMenu, SWT.NONE);
    rssOwlGui.getRSSOwlMenu().updateAccelerator(markUnreadItem, "POP_MARK_UNREAD", false, false);
    markUnreadItem.setEnabled(false);

    MenuItem markAllReadItem = new MenuItem(labelMenu, SWT.NONE);
    rssOwlGui.getRSSOwlMenu().updateAccelerator(markAllReadItem, "POP_MARK_ALL_READ", false, false);
    markAllReadItem.setEnabled(false);

    /** Separator */
    new MenuItem(labelMenu, SWT.SEPARATOR);

    /** Reload newsfeed */
    MenuItem reloadFeed = new MenuItem(labelMenu, SWT.NONE);
    rssOwlGui.getRSSOwlMenu().updateAccelerator(reloadFeed, "MENU_RELOAD", false, false);
    if (!GlobalSettings.isMac())
      reloadFeed.setImage(PaintShop.iconReload);
    reloadFeed.addSelectionListener(new SelectionAdapter() {
      public void widgetSelected(SelectionEvent e) {
        eventManager.actionReload();
      }
    });

    /** Separator */
    new MenuItem(labelMenu, SWT.SEPARATOR);

    /** Search in feed */
    MenuItem searchFeed = new MenuItem(labelMenu, SWT.NONE);
    rssOwlGui.getRSSOwlMenu().updateAccelerator(searchFeed, "BUTTON_SEARCH", true, false);
    if (!GlobalSettings.isMac())
      searchFeed.setImage(PaintShop.iconFind);
    searchFeed.setEnabled(false);

    /** Separator */
    new MenuItem(labelMenu, SWT.SEPARATOR);

    MenuItem mailLinkToFriend = new MenuItem(labelMenu, SWT.NONE);
    rssOwlGui.getRSSOwlMenu().updateAccelerator(mailLinkToFriend, "POP_MAIL_LINK", false, false);
    if (!GlobalSettings.isMac())
      mailLinkToFriend.setImage(PaintShop.iconMail);
    mailLinkToFriend.setEnabled(false);

    MenuItem copyUrlItem = new MenuItem(labelMenu, SWT.NONE);
    rssOwlGui.getRSSOwlMenu().updateAccelerator(copyUrlItem, "POP_COPY_NEWS_URL", false, false);
    copyUrlItem.setEnabled(false);

    /** Separator */
    new MenuItem(labelMenu, SWT.SEPARATOR);

    /** Export */
    MenuItem exportItem = new MenuItem(labelMenu, SWT.CASCADE);
    exportItem.setText(GUI.i18n.getTranslation("BUTTON_EXPORT"));
    if (!GlobalSettings.isMac())
      exportItem.setImage(PaintShop.iconExport);
    exportItem.setEnabled(false);

    /** Separator */
    new MenuItem(labelMenu, SWT.SEPARATOR);

    MenuItem blogNews = new MenuItem(labelMenu, SWT.NONE);
    rssOwlGui.getRSSOwlMenu().updateAccelerator(blogNews, "POP_BLOG_NEWS", false, false);
    blogNews.setEnabled(false);

    /** Init the Mnemonics */
    MenuManager.initMnemonics(labelMenu);

    /** Apply menu */
    errorViewFormContent.setMenu(labelMenu);
  }

  /**
   * Open the URL from the opened CTabItem inside the browser
   */
  void openFeedInBrowser() {

    /** If selected tab displays a feed, pass link to dialog */
    CTabItem tabItem = rssOwlGui.getRSSOwlNewsTabFolder().getNewsHeaderTabFolder().getSelection();
    String link = null;
    if (tabItem != null) {
      TabItemData data = ((TabItemData) tabItem.getData());

      /** Retrieve the URL */
      if (!data.isMessage())
        link = ((TabItemData) tabItem.getData()).getUrl();
    }

    /** Open in browser if set */
    if (StringShop.isset(link))
      eventManager.actionOpenURL(link);
  }
}