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

import net.sourceforge.rssowl.controller.GUI;
import net.sourceforge.rssowl.util.GlobalSettings;

import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.ImageData;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;

import java.io.IOException;
import java.io.InputStream;

/**
 * Factory class for some Paint / Icon concerns in RSSOwl
 * 
 * @author <a href="mailto:bpasero@rssowl.org">Benjamin Pasero </a>
 * @version 1.2.3
 */
public class PaintShop {

  /** Gray ToolBar color */
  public static Color grayToolBarColor;

  /** Gray ViewForm color */
  public static Color grayViewFormColor;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconAddBlogroll;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconAddCategory;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconAddToFavorites;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconBackward;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconBlueStripes;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconCancelOperation;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconCancelOperationDisabled;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconCopy;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconChecked;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconDelete;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconError;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconErrorLense;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconExport;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconExportOpml;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconFeedDiscovery;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconFind;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconFolder;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconFolderSubscribe;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconFolderSubscribeUnread;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconFolderUnread;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconForward;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconHTML;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconImport;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconImportOpml;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconInfo;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconLense;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconLenseUnread;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconMail;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconNew;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconNotRated;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconOwl[] = new Image[4];

  /** Some multiple used Icons in RSSOwl */
  public static Image iconPDF;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconPrint;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconRateSuccess;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconRead;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconReload;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconReloadBrowser;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconRTF;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconSearch;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconSkip;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconSkipDisabled;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconStop;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconSubCategory;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconUnread;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconValidate;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconWarning;

  /** Some multiple used Icons in RSSOwl */
  public static Image iconWorld;

  /** Make the linkColor accessible from all Objects */
  public static Color linkColor;

  /** Make the syntaxHighlightColor accessible from all Objects */
  public static Color syntaxHighlightColor;

  /** First Border Color of ViewForm */
  public static Color viewFormBorderInsideColor;

  /** Second Border Color of ViewForm */
  public static Color viewFormBorderMiddleColor;

  /** Third Border Color of ViewForm */
  public static Color viewFormBorderOutsideColor;

  /** Class required for Image loading */
  private static final Class clazz = PaintShop.class;

  /** Some multiple used Icons in RSSOwl */
  private static Image iconProgress0;

  /** Some multiple used Icons in RSSOwl */
  private static Image iconProgress100;

  /** Some multiple used Icons in RSSOwl */
  private static Image iconProgress20;

  /** Some multiple used Icons in RSSOwl */
  private static Image iconProgress40;

  /** Some multiple used Icons in RSSOwl */
  private static Image iconProgress60;

  /** Some multiple used Icons in RSSOwl */
  private static Image iconProgress80;

  /** This utility class constructor is hidden */
  private PaintShop() {
  // Protect default constructor
  }

  /** Dispose icons */
  public static void disposeIcons() {
    iconNew.dispose();
    iconSubCategory.dispose();
    iconAddCategory.dispose();
    iconDelete.dispose();
    iconImport.dispose();
    iconExport.dispose();
    iconImportOpml.dispose();
    iconAddBlogroll.dispose();
    iconExportOpml.dispose();
    iconError.dispose();
    iconFolder.dispose();
    iconFolderUnread.dispose();
    iconFolderSubscribe.dispose();
    iconFolderSubscribeUnread.dispose();
    iconLense.dispose();
    iconLenseUnread.dispose();
    iconErrorLense.dispose();
    iconForward.dispose();
    iconBackward.dispose();
    iconStop.dispose();
    iconPDF.dispose();
    iconRTF.dispose();
    iconHTML.dispose();
    iconCopy.dispose();
    iconChecked.dispose();
    iconPrint.dispose();
    iconSearch.dispose();
    iconReload.dispose();
    iconFind.dispose();
    iconAddToFavorites.dispose();
    iconMail.dispose();
    iconReloadBrowser.dispose();
    iconRead.dispose();
    iconCancelOperation.dispose();
    iconCancelOperationDisabled.dispose();
    iconSkip.dispose();
    iconNotRated.dispose();
    iconSkipDisabled.dispose();
    iconRateSuccess.dispose();
    iconBlueStripes.dispose();
    iconWorld.dispose();
    iconFeedDiscovery.dispose();
    iconInfo.dispose();
    iconProgress0.dispose();
    iconProgress20.dispose();
    iconProgress40.dispose();
    iconProgress60.dispose();
    iconProgress80.dispose();
    iconProgress100.dispose();
    iconUnread.dispose();
    grayViewFormColor.dispose();
    grayToolBarColor.dispose();
    linkColor.dispose();
    syntaxHighlightColor.dispose();

    /** Application icons */
    for (int a = 0; a < iconOwl.length; a++)
      iconOwl[a].dispose();
  }

  /**
   * Fill an Image with a given color
   * 
   * @param display The display as device for the color
   * @param color The color to display
   * @param width Width of the image
   * @param height Height of the image
   * @return Image Filled image
   */
  public static Image getFilledImage(Display display, RGB color, int width, int height) {
    Image filledImage = new Image(display, width, height);
    Color selectedColor = new Color(display, color);

    /** Paint the image */
    GC gc = new GC(filledImage);
    gc.setBackground(selectedColor);
    gc.fillRectangle(0, 0, width, height);
    gc.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
    gc.drawRectangle(0, 0, width - 1, height - 1);

    /** Cleanup */
    gc.dispose();
    selectedColor.dispose();

    return filledImage;
  }

  /**
   * Get the correct flag for the given language. If a flag for the given
   * language is not found, return the "unknown" flag.
   * 
   * @param locale The language
   * @param curClass Current class
   * @return An image that displays the flag
   */
  public static Image getLanguageFlag(String locale, Class curClass) {

    /** Unknown language, return the "unknown" flag */
    if (locale == null)
      return loadImage("/img/flags/unknown.gif");

    Image flag = null;

    /** The locale consists of language-COUNTRY */
    if (locale.split("-").length > 1) {
      if (curClass.getResource("/img/flags/" + locale.split("-")[1] + ".gif") != null)
        flag = loadImage("/img/flags/" + locale.split("-")[1] + ".gif");
      else if (curClass.getResource("/img/flags/" + locale.split("-")[0] + ".gif") != null)
        flag = loadImage("/img/flags/" + locale.split("-")[0] + ".gif");
    }

    /** The locale consists of either language or COUNTRY */
    else if (!locale.equals("")) {
      if (curClass.getResource("/img/flags/" + locale + ".gif") != null)
        flag = loadImage("/img/flags/" + locale + ".gif");
    }

    /** A flag was found */
    if (flag != null)
      return flag;

    /** Use the "unknown" flag */
    return loadImage("/img/flags/unknown.gif");
  }

  /**
   * Get the progress icon for the given value.
   * 
   * @param value The value (20, 40, 60, 80, 100)
   * @return Image The image of the progress bar
   */
  public static Image getProgressIcon(int value) {
    switch (value) {

      /** Progress Bar indicating 0% */
      case 0:
        return iconProgress0;

        /** Progress Bar indicating 20% */
      case 20:
        return iconProgress20;

        /** Progress Bar indicating 40% */
      case 40:
        return iconProgress40;

        /** Progress Bar indicating 60% */
      case 60:
        return iconProgress60;

        /** Progress Bar indicating 80% */
      case 80:
        return iconProgress80;

        /** Progress Bar indicating 100% */
      case 100:
        return iconProgress100;

        /** Default Progress Bar indicating 0% */
      default:
        return iconProgress0;
    }
  }

  /**
   * Initialize the multiple used colors
   */
  public static void initColors() {

    /** Toolbar and ViewForm Colors */
    RGB grayViewFormRGB;
    RGB grayToolBarRGB;

    /** Decide Colors based on Windows Theme if running on Windows */
    if (GlobalSettings.isWindows()) {
      RGB widgetBackground = GUI.display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND).getRGB();
      RGB listSelection = GUI.display.getSystemColor(SWT.COLOR_LIST_SELECTION).getRGB();

      /** Theme: Windows Blue */
      if (widgetBackground.equals(new RGB(236, 233, 216)) && listSelection.equals(new RGB(49, 106, 197))) {
        grayViewFormRGB = new RGB(241, 240, 234);
        grayToolBarRGB = new RGB(236, 231, 220);
      }

      /** Theme: Windows Classic */
      else if (widgetBackground.equals(new RGB(212, 208, 200)) && listSelection.equals(new RGB(10, 36, 106))) {
        grayViewFormRGB = new RGB(227, 223, 215);
        grayToolBarRGB = new RGB(237, 233, 225);
      }

      /** Theme: Windows Silver */
      else if (widgetBackground.equals(new RGB(224, 223, 227)) && listSelection.equals(new RGB(178, 180, 191))) {
        grayViewFormRGB = new RGB(239, 238, 242);
        grayToolBarRGB = new RGB(234, 233, 237);
      }

      /** Theme: Windows Olive */
      else if (widgetBackground.equals(new RGB(236, 233, 216)) && listSelection.equals(new RGB(147, 160, 112))) {
        grayViewFormRGB = new RGB(244, 243, 226);
        grayToolBarRGB = new RGB(239, 238, 221);
      }

      /** Theme: Windows Royale */
      else if (widgetBackground.equals(new RGB(235, 233, 237)) && listSelection.equals(new RGB(51, 94, 168))) {
        grayViewFormRGB = new RGB(245, 243, 247);
        grayToolBarRGB = new RGB(240, 238, 242);
      }

      /** Any other Theme on Windows */
      else {
        grayViewFormRGB = widgetBackground;
        grayToolBarRGB = widgetBackground;
      }
    }

    /** On any other OS use Widget-Background everywhere */
    else {
      RGB widgetBackground = GUI.display.getSystemColor(SWT.COLOR_WIDGET_BACKGROUND).getRGB();
      grayViewFormRGB = widgetBackground;
      grayToolBarRGB = widgetBackground;
    }

    grayViewFormColor = new Color(GUI.display, grayViewFormRGB);
    grayToolBarColor = new Color(GUI.display, grayToolBarRGB);

    /** ViewForm Border Colors */
    viewFormBorderInsideColor = new Color(GUI.display, 162, 160, 162);
    viewFormBorderMiddleColor = new Color(GUI.display, 173, 171, 168);
    viewFormBorderOutsideColor = new Color(GUI.display, 201, 198, 195);
  }

  /**
   * Initialize the multiple used icons
   */
  public static void initIcons() {

    /** Single used icons */
    iconNew = loadImage("/img/icons/add_category_small.gif");
    iconSubCategory = loadImage("/img/icons/subcat.gif");
    iconDelete = loadImage("/img/icons/delete.gif");
    iconImport = loadImage("/img/icons/import.gif");
    iconExport = loadImage("/img/icons/export.gif");
    iconImportOpml = loadImage("/img/icons/import_opml.gif");
    iconExportOpml = loadImage("/img/icons/export_opml.gif");
    iconFolder = loadImage("/img/icons/folder.gif");
    iconFolderUnread = loadImage("/img/icons/folder_unread.gif");
    iconFolderSubscribe = loadImage("/img/icons/folder_subscribe.gif");
    iconFolderSubscribeUnread = loadImage("/img/icons/folder_subscribe_unread.gif");
    iconLense = loadImage("/img/icons/feed.gif");
    iconLenseUnread = loadImage("/img/icons/feed_unread.gif");
    iconErrorLense = loadImage("/img/icons/feed_error.gif");
    iconForward = loadImage("/img/icons/forward.gif");
    iconBackward = loadImage("/img/icons/backward.gif");
    iconStop = loadImage("/img/icons/stop.gif");
    iconWarning = loadImage("/img/icons/warning.gif");
    iconError = loadImage("/img/icons/error_round.gif");
    iconPDF = loadImage("/img/icons/pdf.gif");
    iconRTF = loadImage("/img/icons/rtf.gif");
    iconHTML = loadImage("/img/icons/html.gif");
    iconCopy = loadImage("/img/icons/copy.gif");
    iconChecked = loadImage("/img/icons/checked.gif");
    iconPrint = loadImage("/img/icons/print.gif");
    iconSearch = loadImage("/img/icons/search_feed.gif");
    iconReload = loadImage("/img/icons/reload.gif");
    iconFind = loadImage("/img/icons/search.gif");
    iconAddToFavorites = loadImage("/img/icons/add_feed.gif");
    iconAddCategory = loadImage("/img/icons/add_category_pop.gif");
    iconAddBlogroll = loadImage("/img/icons/add_subscription.gif");
    iconMail = loadImage("/img/icons/mail.gif");
    iconReloadBrowser = loadImage("/img/icons/reload_browser.gif");
    iconRead = loadImage("/img/icons/read.gif");
    iconUnread = loadImage("/img/icons/unread.gif");
    iconCancelOperation = loadImage("/img/icons/cancel_operation.gif");
    iconCancelOperationDisabled = loadImage("/img/icons/cancel_operation_disabled.gif");
    iconValidate = loadImage("/img/icons/validate.gif");
    iconSkip = loadImage("/img/icons/skip.gif");
    iconSkipDisabled = loadImage("/img/icons/skip_disabled.gif");
    iconRateSuccess = loadImage("/img/icons/rate_success.gif");
    iconNotRated = loadImage("/img/icons/rate_norate.gif");
    iconBlueStripes = loadImage("/img/icons/pref.gif");
    iconWorld = loadImage("/img/icons/world.gif");
    iconFeedDiscovery = loadImage("/img/icons/feed_discovery.gif");
    iconInfo = loadImage("/img/icons/info.gif");

    /** Progress icons */
    iconProgress0 = loadImage("/img/icons/progress0.gif");
    iconProgress20 = loadImage("/img/icons/progress20.gif");
    iconProgress40 = loadImage("/img/icons/progress40.gif");
    iconProgress60 = loadImage("/img/icons/progress60.gif");
    iconProgress80 = loadImage("/img/icons/progress80.gif");
    iconProgress100 = loadImage("/img/icons/progress100.gif");

    /** Shell Icons for 16, 20 and 24 Depth */
    iconOwl[0] = loadImage("/img/16x16.gif");
    iconOwl[1] = loadImage("/img/20x20.gif");
    iconOwl[2] = loadImage("/img/24x24.gif");

    /** 32 Depth Shell Icon - PNG on Windows */
    if (GlobalSettings.isWindows())
      iconOwl[3] = loadImage("/img/32x32.png");

    /** 32 Depth Shell Icon - GIF on other OS */
    else
      iconOwl[3] = loadImage("/img/32x32.gif");
  }

  /**
   * Set the color for the links
   * 
   * @param display The display
   */
  public static void initLinkColor(Display display) {
    linkColor = new Color(display, GlobalSettings.linkColor);
  }

  /**
   * Set the color for the syntaxhighlight
   * 
   * @param display The display
   */
  public static void initSyntaxHighlightColor(Display display) {
    syntaxHighlightColor = new Color(display, GlobalSettings.syntaxHighlightColor);
  }

  /**
   * Check the given Image for being NULL or disposed. Return false in that
   * case.
   * 
   * @param image The image to check
   * @return boolean TRUE if the Image is available
   */
  public static boolean isset(Image image) {
    return (image != null && !image.isDisposed());
  }

  /**
   * Load an Image from the given Path using an InputStream that is closed after
   * the Image has been loaded.
   * 
   * @param path Path to the Image (must start with "/")
   * @return Image The loaded Image or NULL
   */
  public static Image loadImage(String path) {
    return loadImage(path, false);
  }

  /**
   * Load an Image from the given Path using an InputStream that is closed after
   * the Image has been loaded.
   * 
   * @param path Path to the Image (must start with "/")
   * @param hideOnMac If TRUE, hide the Image on Mac
   * @return Image The loaded Image or NULL
   */
  public static Image loadImage(String path, boolean hideOnMac) {

    /** Do not show Icon on Mac OS */
    if (hideOnMac && GlobalSettings.isMac())
      return null;

    /** Load Image from InputStream */
    Image image;
    InputStream inS = null;

    try {
      inS = clazz.getResourceAsStream(path);
      image = new Image(GUI.display, inS);
      inS.close();
    }

    /** File not Found */
    catch (IOException e) {
      image = null;
    }

    /** Finally try to close the Stream */
    finally {
      if (inS != null) {
        try {
          inS.close();
        } catch (IOException e) {
          GUI.logger.log("loadImage()", e);
        }
      }
    }

    /** Return the Image */
    return image;
  }

  /**
   * Takes the given Image and creates a new one with the given Size. The new
   * Image is not a scaled version of the source Image, only a clipped one.
   * 
   * @param display The display as device for the image.
   * @param src The source Image to resize.
   * @param width The width of the new Image.
   * @param height The height of the new Image.
   * @param disposeSrc If TRUE, dispose the source Image.
   * @return Image The resized Image.
   */
  public static Image sizeTo(Display display, Image src, int width, int height, boolean disposeSrc) {

    /** Create this temp Image to access the ImageData */
    Image img = new Image(display, width, height);
    ImageData data = img.getImageData();
    img.dispose();

    /** Make white the transparent Pixel */
    int whitePixel = data.palette.getPixel(new RGB(255, 255, 255));
    data.transparentPixel = whitePixel;
    img = new Image(display, data);

    /** Draw the Image */
    GC gc = new GC(img);
    Rectangle srcBounds = src.getBounds();
    gc.drawImage(src, (width - srcBounds.width) / 2, (height - srcBounds.height) / 2);
    gc.dispose();

    /** Dispose source if set */
    if (disposeSrc)
      src.dispose();

    return img;
  }
}