//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 IBM Corporation and others.
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// which accompanies this distribution, and is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// Contributors:
// IBM Corporation - initial implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.library.prefs;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.eclipse.epf.library.LibraryPlugin;
import org.eclipse.epf.library.edit.process.IBSItemProvider;
import org.eclipse.jface.preference.IPreferenceStore;

import com.ibm.icu.util.StringTokenizer;

/**
 * utility class to handle the process element layout preferences
 * 
 * @author Jinhua Xi
 * @since 1.0
 *
 */
public class PreferenceUtil {
		
	private static Properties xslParams;
	private static Map colIdLabelMap = new HashMap();
	
	// quick solution, the team column for the WBS view.
	// 162783 - Publish team information in WBS for TDs
	private static BSColumn teamCol = null;

	private static final String ID_STEPS = "steps"; //$NON-NLS-1$
	static {
		try {
			Properties params = LibraryPlugin.getDefault().getProperties(
					"/layout/xsl/resources.properties"); //$NON-NLS-1$
			
			setXslProperties(params);
			
		} catch (IOException e) {
		}
	}
	
	public static void setXslProperties(Properties newXslParams) {
		xslParams = newXslParams;	
		
		colIdLabelMap.put(IBSItemProvider.COL_ID, getLabel("indexText")); //$NON-NLS-1$
		colIdLabelMap.put(IBSItemProvider.COL_NAME, getLabel("nameText")); //$NON-NLS-1$
		colIdLabelMap.put(IBSItemProvider.COL_PRESENTATION_NAME, getLabel("breakdownElementText")); //$NON-NLS-1$
		colIdLabelMap.put(ID_STEPS, getLabel("stepsText"));		 //$NON-NLS-1$
		colIdLabelMap.put(IBSItemProvider.COL_PREFIX, getLabel("prefixText")); //$NON-NLS-1$
		colIdLabelMap.put(IBSItemProvider.COL_TYPE, getLabel("typeText")); //$NON-NLS-1$
		colIdLabelMap.put(IBSItemProvider.COL_MODEL_INFO, getLabel("modelInfoText")); //$NON-NLS-1$
		colIdLabelMap.put(IBSItemProvider.COL_PREDECESSORS, getLabel("predecessorsText")); //$NON-NLS-1$
		colIdLabelMap.put(IBSItemProvider.COL_IS_REPEATABLE, getLabel("repeatableText")); //$NON-NLS-1$
		colIdLabelMap.put(IBSItemProvider.COL_IS_ONGOING, getLabel("ongoingText")); //$NON-NLS-1$
		colIdLabelMap.put(IBSItemProvider.COL_IS_EVENT_DRIVEN, getLabel("eventDrivenText")); //$NON-NLS-1$
		colIdLabelMap.put(IBSItemProvider.COL_IS_OPTIONAL, getLabel("optionalText")); //$NON-NLS-1$
		colIdLabelMap.put(IBSItemProvider.COL_IS_PLANNED, getLabel("plannedText")); //$NON-NLS-1$
		colIdLabelMap.put(IBSItemProvider.COL_HAS_MULTIPLE_OCCURRENCES, getLabel("multipleOccurrencesText")); //$NON-NLS-1$

		colIdLabelMap.put(IBSItemProvider.COL_TEAMS, getLabel("teamText")); //$NON-NLS-1$

		colIdLabelMap.put(IBSItemProvider.COL_DELIVERABLE, getLabel("deliverableText")); //$NON-NLS-1$
		colIdLabelMap.put(IBSItemProvider.COL_ENTRY_STATE, getLabel("entryStateText")); //$NON-NLS-1$
		colIdLabelMap.put(IBSItemProvider.COL_EXIT_STATE, getLabel("exitStateText")); //$NON-NLS-1$

	}
	
	private static String getLabel(String key) {
		String label = xslParams.getProperty(key);
		if ( label == null ) {
			System.out.println("Can't find property entry for " + key); //$NON-NLS-1$
			label = key;
		}
		return label;
	}
	
	/**
	 * get a list of columns for WBS layout
	 * @return List of BSColumn objects
	 */
	public static List getWBSColumns() {
		List cols = getPreferenceItems(PreferenceConstants.PREF_WBS_COLUMNS);
		
		// if the TBS columns has team, also add to the WBS
		// 162783 - Publish team information in WBS for TDs
		teamCol = null;
		getTBSColumns();
		if ( teamCol != null ) {
			cols.add(cols.size(), teamCol);
		}
		return cols;
	}
	
	/**
	 * get a list of columns for TBS layout
	 * @return List of BSColumn objects
	 */
	public static List getTBSColumns() {
		return getPreferenceItems(PreferenceConstants.PREF_TBS_COLUMNS);
	}
	
	/**
	 * get a list of columns for WPBS layout
	 * @return List of BSColumn objects
	 */
	public static List getWPBSColumns() {
		return getPreferenceItems(PreferenceConstants.PREF_WPBS_COLUMNS);
	}
	
	/**
	 * validate the columns
	 */
	public static void validatePreferences() {
		// call the method to make sure the default is loaded
		getWBSColumns();
		getTBSColumns();
		getWPBSColumns();
	}
	
	private static List getPreferenceItems(String key) {
		
		IPreferenceStore store = LibraryPlugin.getDefault().getPreferenceStore();		
		String str = store.getString(key);
		if (str == null) {
			str = store.getDefaultString(key);
		}
		
		if ( str == null || str.length() == 0 ) {
			str = getDefault(key);
			store.setValue(key, str);
		}
		
		List items = new ArrayList();
		StringTokenizer tokens = new StringTokenizer(str, ","); //$NON-NLS-1$
		while (tokens.hasMoreTokens()) {
			String id = tokens.nextToken().trim();		
			if (id != null && id.length() != 0 ) {
				
				BSColumn col = new BSColumn(id, getColText(id));
				items.add(col);
				// add steps column for WBS
				if ( key.equals(PreferenceConstants.PREF_WBS_COLUMNS) 
						&& id.equals(IBSItemProvider.COL_PRESENTATION_NAME) ) {
					col = new BSColumn(ID_STEPS, getColText(ID_STEPS));
					items.add(col);
				}
				
				// save the team column for WBS
				// 162783 - Publish team information in WBS for TDs
				if ( IBSItemProvider.COL_TEAMS.equals(id) ) {
					teamCol = col;
				}
			}
		}
		
		return items;
	}
	
	private static String getColText(String key) {
		String text = (String)colIdLabelMap.get(key);
		if ( text == null ) {
			System.out.println("No label defined for column " + key);  //$NON-NLS-1$
			text = key;
		}
		
		return text;
	}
	
	private static  String getDefault(String key) {
		if ( PreferenceConstants.PREF_WBS_COLUMNS.equals(key) ) {
			return toString(PreferenceConstants.DEFAULT_WBS_COLUMNS);
		}
		
		if ( PreferenceConstants.PREF_TBS_COLUMNS.equals(key) ) {
			return toString(PreferenceConstants.DEFAULT_TBS_COLUMNS);
		}
		
		if ( PreferenceConstants.PREF_WPBS_COLUMNS.equals(key) ) {
			return toString(PreferenceConstants.DEFAULT_WPBS_COLUMNS);
		}
		
		return null;
	}
	
	private static String toString(String[] ids) {
		StringBuffer strBuf = new StringBuffer();
		int max = ids.length - 1;
		for (int i = 0; i < max; i++) {
			strBuf.append(ids[i])
					.append(',');
		}
		strBuf.append(ids[ids.length-1]);
		return strBuf.toString();
	}

	public static void saveSelectedConfigIntoPersistence(String configName) {
		IPreferenceStore store = LibraryPlugin.getDefault()
				.getPreferenceStore();
		store
				.setValue(
						LibraryPreferenceConstants.PREF_SELECTED_CONFIG_IN_LAST_SESSION,
						configName);
		LibraryPlugin.getDefault().savePluginPreferences();
	}

	public static String getSavedLastConfig() {
		IPreferenceStore store = LibraryPlugin.getDefault()
				.getPreferenceStore();
		return store
				.getString(LibraryPreferenceConstants.PREF_SELECTED_CONFIG_IN_LAST_SESSION);
	}
	
}
