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

import net.sourceforge.blowfishj.BlowfishEasy;
import net.sourceforge.rssowl.controller.GUI;
import net.sourceforge.rssowl.util.shop.StringShop;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Enumeration;
import java.util.Hashtable;

/**
 * This class handles sensitive user data.
 * 
 * @author <a href="mailto:bpasero@rssowl.org">Benjamin Pasero </a>
 * @version 1.2.3
 */
public class CryptoManager {

  /** Unique key for the proxy domain (NTLM only) */
  public static final String PROXY_DOMAIN_KEY = "PROXY_DOMAIN_KEY";

  /** Unique key for the proxy password */
  public static final String PROXY_PASSWORD_KEY = "PROXY_PASSWORD_KEY";

  /** Unique key for the proxy username */
  public static final String PROXY_USER_KEY = "PROXY_USER_KEY";

  /** An instance of the CryptoManager */
  private static CryptoManager instance;

  private BlowfishEasy blowFish;
  private Hashtable crypta;

  /**
   * Called from the static factory Method
   */
  private CryptoManager() {
    blowFish = new BlowfishEasy(new char[] { 114, 115, 115, 111, 119, 108, 50, 48, 48, 52, 126 });
    loadData();
  }

  /**
   * Instantiate a new CryptoManager when this method is called the first time
   * and return it.
   * 
   * @return CryptoManager An instance of the CryptoManager
   */
  public static CryptoManager getInstance() {
    if (instance == null)
      instance = new CryptoManager();
    return instance;
  }

  /**
   * Add an item to the crypta.
   * 
   * @param key Unique key of the item
   * @param value Value of the item
   */
  public void addItem(String key, String value) {
    if (StringShop.isset(value))
      crypta.put(key, value);
  }

  /**
   * Get an item from the crypta.
   * 
   * @param key Unique key of the item
   * @return String The value of the item
   */
  public String getItem(String key) {
    return (String) crypta.get(key);
  }

  /**
   * Check if the crypta contains an item for the given key
   * 
   * @param key Unique key of the item
   * @return boolean TRUE if item is in crypta
   */
  public boolean hasItem(String key) {
    return (key != null) && crypta.containsKey(key);
  }

  /**
   * Load the proxy Domain from the crypta.
   * 
   * @return String The proxy Domain or an empty String if not stored in the
   * crypta
   */
  public String loadProxyDomain() {
    if (crypta.containsKey(PROXY_DOMAIN_KEY))
      return (String) crypta.get(PROXY_DOMAIN_KEY);
    return "";
  }

  /**
   * Load the proxy password from the crypta.
   * 
   * @return String The proxy password or an empty String if not stored in the
   * crypta
   */
  public String loadProxyPassword() {
    if (crypta.containsKey(PROXY_PASSWORD_KEY))
      return (String) crypta.get(PROXY_PASSWORD_KEY);
    return "";
  }

  /**
   * Load the proxy username from the crypta.
   * 
   * @return String The proxy username or an empty String if not stored in the
   * crypta
   */
  public String loadProxyUser() {
    if (crypta.containsKey(PROXY_USER_KEY))
      return (String) crypta.get(PROXY_USER_KEY);
    return "";
  }

  /**
   * Remove an item from the crapty.
   * 
   * @param key Unique key of the item.
   */
  public void removeItem(String key) {
    if (hasItem(key))
      crypta.remove(key);
  }

  /**
   * Save the crypta to a file.
   */
  public void saveData() {
    try {
      encryptData();
      FileOutputStream fileOutStream = new FileOutputStream(GlobalSettings.CRYPT_FILE);
      ObjectOutputStream objOutStream = new ObjectOutputStream(fileOutStream);
      objOutStream.writeObject(crypta);
      objOutStream.close();
    } catch (IOException e) {
      GUI.logger.log("saveData", e);
    }
  }

  /**
   * Decrypt the crypta.
   */
  private void decryptData() {
    Enumeration keys = crypta.keys();
    while (keys.hasMoreElements()) {
      String key = (String) keys.nextElement();
      crypta.put(key, blowFish.decryptString((String) crypta.get(key)));
    }
  }

  /**
   * Encrypt the crypta.
   */
  private void encryptData() {
    Enumeration keys = crypta.keys();
    while (keys.hasMoreElements()) {
      String key = (String) keys.nextElement();
      crypta.put(key, blowFish.encryptString((String) crypta.get(key)));
    }
  }

  /**
   * Load the crypta from a file.
   */
  private void loadData() {
    try {
      FileInputStream fileInStream = new FileInputStream(GlobalSettings.CRYPT_FILE);
      ObjectInputStream objInStream = new ObjectInputStream(fileInStream);
      crypta = (Hashtable) objInStream.readObject();
      decryptData();
      objInStream.close();
    } catch (IOException e) {
      GUI.logger.log(e.getMessage());
    } catch (ClassNotFoundException e) {
      GUI.logger.log(e.getMessage());
    }

    /** In the case of any error create empty Hashtable */
    finally {
      if (crypta == null)
        crypta = new Hashtable();
    }
  }
}