package org.eclipse.epf.export.wizards;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.epf.common.utils.FileUtil;
import org.eclipse.epf.common.utils.StrUtil;
import org.eclipse.epf.export.ExportPlugin;
import org.eclipse.epf.library.LibraryPlugin;
import org.eclipse.epf.library.prefs.LibraryPreferenceConstants;
import org.eclipse.epf.library.ui.preferences.LibraryUIPreferences;

import com.ibm.icu.util.StringTokenizer;

/**
 * Manages the export UI preferences.
 * 
 * @author hopeshared
 * @since 1.2
 */
public class ExportUIPreferences {
	
	/**
	 * The recently opened dir preference delimiter.
	 */
	public static final String PREFERENCE_DELIMITER = ";"; //$NON-NLS-1$
	
	/**
	 * set <code>10</code> as the default length of the combo popup list
	 */
	private static final int DEFAIL_LIST_LENGTH = 10;
	
	/**
	 * The Export Plugin preference key.
	 */
	public static final String LAST_EXPORT_PLUGIN_PATH = "lastExportPluginPath"; //$NON-NLS-1$
	
	/**
	 * The Export Configuration preference key.
	 */
	public static final String LAST_EXPORT_CONFIG_PATH = "lastExportConfigPath"; //$NON-NLS-1$


	/**
	 * Returns the default export path.
	 * 
	 * @return The default export path.
	 */	
	public static String getDefaultExportPath() {
		String defExportPPath = System.getProperty("user.home") + //$NON-NLS-1$
				FileUtil.FILE_SEP + LibraryUIPreferences.getApplicationShortName() + 
				FileUtil.FILE_SEP + "Export"; //$NON-NLS-1$
		return defExportPPath;
	}
	
	/**
	 * Gets the recently opened method plugin dir preference.
	 * 
	 * @return a collection of String
	 */
	public static List getRecentlyExportedPluginDirs() {
		List dirs = getPropertyList(LAST_EXPORT_PLUGIN_PATH);
		List result = new ArrayList();
		if (dirs.size() > 0) {
			for (Iterator it = dirs.iterator(); it.hasNext();) {
				String dir = (String) it.next();
				result.add(dir);
			}
		}
		return result;
	}
	
	/**
	 * Sets the recently opened method plugin preference.
	 * 
	 * @param dir   export plugin dir
	 */
	public static void addRecentlyExportPluginDir(String dir) {
		if (dir == null || dir.length()==0) {
			return;
		}

		List dirs = getRecentlyExportedPluginDirs();

		addProperty(dirs, dir, LAST_EXPORT_PLUGIN_PATH);
	}
	
	/**
	 * Gets the recently export config dirs preference.
	 * 
	 * @return a collection of String
	 */
	public static List getRecentlyExportedConfigDirs() {
		//TODO
		List dirs = getPropertyList(LAST_EXPORT_CONFIG_PATH);
		List result = new ArrayList();
		if (dirs.size() > 0) {
			for (Iterator it = dirs.iterator(); it.hasNext();) {
				String dir = (String) it.next();
				result.add(dir);
			}
		}
		return result;
	}
	
	/**
	 * Sets the recently opened method config dir preference.
	 * 
	 * @param dir   export config dir
	 */
	public static void addRecentlyExportConfigDir(String dir) {
		if (dir == null || dir.length()==0) {
			return;
		}

		List dirs = getRecentlyExportedConfigDirs();

		addProperty(dirs, dir, LAST_EXPORT_CONFIG_PATH);
	}
	
	/**
	 * Add the property to the first position.
	 * 
	 * @param oldPropertyList   old property list
	 * @param newProperty       new property value 
	 * @param propertyKey       target property key
	 */
	private static void addProperty(List oldPropertyList, String newProperty, String propertyKey){
		List dirsResult = new ArrayList();
		
		if(oldPropertyList.contains(newProperty))
			oldPropertyList.remove(newProperty);
		
		dirsResult.add(0, newProperty);
		
		for (int i=0; i<oldPropertyList.size(); i++) {
			String path = (String) oldPropertyList.get(i);
			dirsResult.add(i+1, path);
		}
		
		if(dirsResult.size()>getListLength())
			dirsResult = dirsResult.subList(0, getListLength());
			
		setPropertyList(propertyKey, StrUtil.convertListToStrArray(dirsResult));
	}
	
	/**
	 * Returns the string values associated with the named preference as a
	 * <ocde>List</code>.
	 */
	private static List getPropertyList(String name) {
		List list = convertToList(ExportPlugin.getDefault().getPreferenceStore()
				.getString(name));
		int length = getListLength();
		if(list.size()>length){
			list = list.subList(0, length);
		}
		return list;
	}
	
	/**
	 * Saves the given string values associated with the named preference.
	 */
	private static void setPropertyList(String name, String[] items) {
		StringBuffer buffer = new StringBuffer();
		for (int i = 0; i < items.length; i++) {
			buffer.append(items[i]);
			buffer.append(PREFERENCE_DELIMITER);
		}
		ExportPlugin.getDefault().getPreferenceStore().setValue(name,
				buffer.toString());
	}
	
	/**
	 * Converts the supplied PREFERENCE_DELIMITER delimited string into a
	 * <code>List</code> object.
	 */
	private static ArrayList convertToList(String preferenceValue) {
		ArrayList topics = new ArrayList();
		StringTokenizer tokenizer = new StringTokenizer(preferenceValue,
				PREFERENCE_DELIMITER);
		int tokenCount = tokenizer.countTokens();
		for (int i = 0; i < tokenCount; i++) {
			topics.add(tokenizer.nextToken());
		}
		return topics;
	}
	
	/**
	 * @return the length of list
	 */
	public static int getListLength(){
		String length = LibraryPlugin.getDefault().getPreferenceStore().getString(LibraryPreferenceConstants.PREF_DEFAULT_HISTORY_SIZE);
		int ll = 0;
		if(length!=null && length.length()>0){
			try{
				ll = Integer.parseInt(length);
			}catch (Exception e){
				
			}
		}
		return ll>0?ll:DEFAIL_LIST_LENGTH;
	}
}
