/*   **********************************************************************  **
 **   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.controller.MessageBoxFactory;
import net.sourceforge.rssowl.dao.ConnectionManager;
import net.sourceforge.rssowl.model.Channel;
import net.sourceforge.rssowl.util.DateParser;
import net.sourceforge.rssowl.util.GlobalSettings;

import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.FileDialog;
import org.eclipse.swt.widgets.Shell;
import org.jdom.Document;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;

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

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

  /**
   * Check if the given Path points to an existing file.
   * 
   * @param path The path to check.
   * @return boolean TRUE if the File exists
   */
  public static boolean exists(String path) {
    if (!StringShop.isset(path))
      return false;

    return new File(path).exists();
  }

  /**
   * Open a FileDialog for the user to choose where to export the XML holding
   * the category(s).
   * 
   * @param parent The parent Shell of the Dialog
   * @param name Suggested name for the file
   * @param format Preselected formats
   * @throws IOException If an IO Error occurs
   */
  public static void exportCategory(Shell parent, String name, String format[]) throws IOException {
    String fileName = getFilePath(parent, format, name, SWT.SAVE, null, null);

    /** File must not be NULL */
    if (fileName != null) {

      /** If File exists and the user clicked YES to overwrite it, proceed */
      if (!new File(fileName).exists() || overwrite())
        SimpleFileShop.copy(GlobalSettings.TEMP_EXPORT_FILE, fileName);
    }
  }

  /**
   * Open a FileDialog for the user to choose where to export the "user.xml"
   * 
   * @param parent The parent Shell of the Dialog
   * @throws IOException If an IO Error occurs
   */
  public static void exportUserSettings(Shell parent) throws IOException {
    String fileName = getFilePath(parent, new String[] { "*.xml", "*.*" }, "user.xml", SWT.SAVE, null, GUI.i18n.getTranslation("MENU_EXPORT"));

    /** File must not be NULL */
    if (fileName != null) {

      /** If File exists and the user clicked YES to overwrite it, proceed */
      if (!new File(fileName).exists() || overwrite())
        SimpleFileShop.copy(GlobalSettings.RSSOWL_SETTINGS_FILE, fileName);
    }
  }

  /**
   * Read the contents from an InputStream into a String.
   * 
   * @param inS Any InputStream (e.g. from an URL)
   * @return String A new String from the byte array
   */
  public static String getContent(InputStream inS) {
    String line;
    StringBuffer content = new StringBuffer();

    /** User might have interrupted the connection manager */
    if (inS == null)
      return "";

    try {
      BufferedReader in = new BufferedReader(new InputStreamReader(inS));

      /** Read all lines and append to Content */
      while ((line = in.readLine()) != null)
        content.append(line).append('\n');

      /** Close the Stream */
      in.close();
    } catch (IOException e) {
      GUI.logger.log("getContent()", e);
      return "";
    }

    /** Create the String */
    return content.toString();
  }

  /**
   * Read the contents from an URL into a String.
   * 
   * @param url Any valid URL that is online
   * @return String A new String from the contents of the URL
   * @throws IOException If an error occurs
   */
  public static String getContent(URL url) throws IOException {

    /** Connect via ConnectionManager */
    ConnectionManager connectionManager = new ConnectionManager(url.toExternalForm());
    connectionManager.setShowLoginDialogIfRequired(false);
    connectionManager.connect();

    /** Read content from the resulting stream */
    String content = getContent(connectionManager.getInputStream());

    /** Close connection */
    connectionManager.closeConnection();

    return content;
  }

  /**
   * Get a path to a file from the user
   * 
   * @param parent The parent Shell of the dialog
   * @param formats List of selectable file extensions
   * @param fileName The preselected filename for the dialog
   * @param style Either SWT.OPEN or SWT.SAVE
   * @param path If not NULL browser into given directory
   * @param title The Dialogs Title or NULL if none.
   * @return String The file path
   */
  public static String getFilePath(Shell parent, String[] formats, String fileName, int style, String path, String title) {
    FileDialog fileDialog = new FileDialog(parent, style);

    /** Set filter extensions */
    if (formats != null)
      fileDialog.setFilterExtensions(formats);

    /** Set filter path */
    if (path != null)
      fileDialog.setFilterPath(path);

    /** Set file name */
    if (fileName != null)
      fileDialog.setFileName(fileName);

    /** Set Title if given */
    if (StringShop.isset(title))
      fileDialog.setText(title);

    return fileDialog.open();
  }

  /**
   * Get a path to a file from the user
   * 
   * @param formats List of selectable file extensions
   * @param fileName The preselected filename for the dialog
   * @param style Either SWT.OPEN or SWT.SAVE
   * @param path If not NULL browser into given directory
   * @param title The Dialogs Title or NULL if none.
   * @return String The file path
   */
  public static String getFilePath(String[] formats, String fileName, int style, String path, String title) {
    return getFilePath(GUI.shell, formats, fileName, style, path, title);
  }

  /**
   * Get the FilePath from the user to save the file
   * 
   * @param fileName Preselected filename
   * @param format Format of the file to save
   * @param title The Dialogs Title or NULL if none.
   * @return String Save path
   */
  public static String getSavePath(String fileName, String format, String title) {
    String selectedFileName = getFilePath(new String[] { "*." + format, "*.*" }, fileName, SWT.SAVE, null, title);

    /** File must not be NULL */
    if (selectedFileName != null) {

      /** If File exists and the user clicked YES to overwrite it, proceed */
      if (!new File(selectedFileName).exists() || overwrite()) {
        return selectedFileName;
      }
    }
    return null;
  }

  /**
   * Open a FileDialog for the user to choose from which file the settings
   * should be imported
   * 
   * @param parent The parent Shell of the Dialog
   * @return int Either OP_SUCCESSFULL, OP_FAILED or OP_ABORTED as result of the
   * operation
   * @throws IOException If an IO Error occurs
   */
  public static int importUserSettings(Shell parent) throws IOException {
    String fileName = getFilePath(parent, new String[] { "*.xml", "*.*" }, null, SWT.OPEN, null, GUI.i18n.getTranslation("MENU_IMPORT"));

    /** Abort operation if fileName is not selected */
    if (fileName == null)
      return OP_ABORTED;

    /** Check if File is a valid file for import of settings */
    if (XMLShop.isValidUserXML(fileName)) {

      /** Overwrite user.xml file */
      SimpleFileShop.copy(fileName, GlobalSettings.RSSOWL_SETTINGS_FILE);
      return OP_SUCCESSFULL;
    }
    return OP_FAILED;
  }

  /**
   * Test if the medium from where RSSOwl is executed is writeable
   * 
   * @param file A file to write
   * @return TRUE if the medium is writeable
   */
  public static boolean isMediumWriteable(File file) {
    try {
      file.createNewFile();
      file.delete();
    } catch (IOException e) {
      return false;
    }
    return true;
  }

  /**
   * Open a FileDialog for the user to choose where to save the RSS XML of the
   * selected news feed
   * 
   * @param rssUrl URL / Path to the rss xml
   * @param fileName Sugggest a filename with current date
   */
  public static void saveRSSXML(String rssUrl, String fileName) {
    String selectedFileName = getFilePath(new String[] { "*.xml", "*.*" }, fileName, SWT.SAVE, null, GUI.i18n.getTranslation("MENU_SAVE"));

    /** File must not be NULL */
    if (selectedFileName != null) {

      /** If File exists and the user clicked YES to overwrite it, proceed */
      if (!new File(selectedFileName).exists() || overwrite()) {

        /** Copy rss xml to destination file */
        copyXML(rssUrl, selectedFileName);
      }
    }
  }

  /**
   * Save current selected news XML to a file
   * 
   * @return TRUE if save was successfull
   */
  public static boolean saveSelectedNewsFeed() {

    /** Get selected Channel */
    Channel rssChannel = GUI.rssOwlGui.getRSSOwlNewsTabFolder().getSelectedChannel();

    /** Channel must not be null */
    if (rssChannel == null)
      return false;

    /** Transform Channel into Document */
    Document document = rssChannel.toDocument();

    /** Write the xml to a temp-file */
    XMLShop.writeXML(document, GlobalSettings.TEMP_FEED_FILE, true);

    /** Get a filename suggestion for the RSS */
    String fileName = suggestRSSFileName(GUI.rssOwlGui.getRSSOwlNewsTabFolder().getNewsHeaderTabFolder().getSelection().getText());

    /** Save the RSS */
    saveRSSXML(GlobalSettings.TEMP_FEED_FILE, fileName);

    return true;
  }

  /**
   * Suggest a filename for a RSS newsfeed with using the current date.
   * 
   * @param initName The initial name suggestion
   * @return String The suggested filename
   */
  public static String suggestRSSFileName(String initName) {

    /** Build the current Date */
    String curDate = DateParser.dateToFileName(DateParser.formatDate());

    /** Suggest a filename */
    String fileName = initName + "_rss_" + curDate + ".xml";

    /** Remove possible special chars from name, this is not valid as filename */
    fileName = StringShop.createFileName(fileName);

    return fileName;
  }

  /**
   * Open dialog to ask if the file should be overwritten
   * 
   * @return TRUE if file should be overwritten
   */
  private static boolean overwrite() {
    return MessageBoxFactory.showMessage(GUI.shell, SWT.ICON_WARNING | SWT.YES | SWT.NO, GUI.i18n.getTranslation("MESSAGEBOX_TITLE_ATTENTION"), GUI.i18n.getTranslation("MESSAGEBOX_FILE_EXISTS")) == SWT.YES;
  }

  /**
   * Copy a XML to another file
   * 
   * @param url URL / Path to the rss xml
   * @param dest Path to the destinationfile
   */
  static void copyXML(String url, String dest) {
    try {

      /** Get the InputStream for the rss xml */
      InputStream inputStream = XMLShop.getXMLStream(url);

      /** Copy rss xml to new file */
      if (inputStream != null)
        copy(XMLShop.getXMLStream(url), new BufferedOutputStream(new FileOutputStream(dest)));
    } catch (IOException e) {
      GUI.logger.log("copyRssXml", e);
    }
  }
}