//------------------------------------------------------------------------------
// Copyright (c) 2005, 2007 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.services;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import org.eclipse.epf.common.utils.StrUtil;
import org.eclipse.epf.library.LibraryService;
import org.eclipse.epf.library.layout.Bookmark;
import org.eclipse.epf.persistence.MultiFileResourceSetImpl;
import org.eclipse.epf.uma.MethodElement;


public class NameCache {
	
	private static NameCache instance = new NameCache();
	private Map<String, String> aMap = new HashMap<String, String>();
	private Set<ElementFile> aSet = new HashSet<ElementFile>();
	private Map<String, String> gMap = new HashMap<String, String>();

	/**
	 * Returns the shared instance.
	 */
	public static NameCache getInstance() {
		return instance;
	}

	/**
	 * Private constructor to prevent this class from being instantiated.
	 */
	private NameCache() {
	}
	
	public void clear() {
		aMap.clear();
		aSet.clear();
		gMap.clear();
	}
	
	/**
	 * get the file name with the given prefix and extension
	 * @param element MethodElement
	 * @param namePrefix String prefix for the name
	 * @param nameSuffix String suffix for the name
	 * @param ext String file extension, for example, ".html"
	 * @return String
	 */	 
	public String getFileName(MethodElement element, String namePrefix,
			String nameSuffix, String ext) {
		
		String existingElementName = null;
		StringBuffer buffer = new StringBuffer();
		if (namePrefix != null) {
			buffer.append(namePrefix);
		}
		
		if (element.getName() == "")
			return "0" + ext; //$NON-NLS-1$
		
		if (!gMap.isEmpty()) {
			existingElementName =  (String) gMap.get(element.getGuid());
		}
		// Browsing: Browsing CP with special chars failed with
		// blank pages and Script Error need to make a valid file name
		buffer.append((existingElementName != null) ? existingElementName : StrUtil.removeSpecialCharacters(element.getName()));
		if (nameSuffix != null) {
			buffer.append(nameSuffix);
		}

		if (ext != null) {
			if (ext.indexOf(".") < 0) //$NON-NLS-1$
			{
				ext = "." + ext; //$NON-NLS-1$
			}
			buffer.append(ext);
		}

		ElementFile a = new ElementFile(element.getGuid(), buffer.toString());
		
		if (a != null && aSet.add(a)) {
			int extDot = a.getFileName().lastIndexOf(".");
			aMap.put((extDot < 0) ? a.getFileName() : a.getFileName().substring(0, extDot), element.getGuid());			 
			gMap.put(element.getGuid(), (extDot < 0) ? a.getFileName() : a.getFileName().substring(0, extDot));
		}

		return a.getFileName(); 
	}
	
	public String getFileName(MethodElement element) {
		
		StringBuffer buffer = new StringBuffer(StrUtil.removeSpecialCharacters(element.getName()));
		
		ElementFile a = new ElementFile(element.getGuid(), buffer.toString());
		
		if (a != null && aSet.add(a)) {
			aMap.put(a.getFileName(), element.getGuid());
//			gMap.put(element.getGuid(), a.getFileName());
		}

		return a.getFileName(); 
	}
	
	public String getFileName(String guid) {
		
		if (!gMap.isEmpty()) {
			return (String) gMap.get(guid);
		}
		return null; 
	}

	/**
	 * get the guid from the file name, assuming the file name is generated from an element, 
	 * return null if not found.
	 * @param fileName String
	 * @return String
	 */
	public String getGuidFromFileName(String fileName) {
		if (fileName == null) {
			return null;
		}			
		
		String guid = null;
		
		int idx = fileName.lastIndexOf("/");
		int lastIdx = fileName.lastIndexOf(".");

		if (idx > -1) {
			guid = (String) aMap.get((lastIdx > -1 && idx < lastIdx) ? 
					fileName.substring(idx+1, lastIdx) : (idx < fileName.length()) ? 
							fileName.substring(idx+1) : null);
		} else {
			guid = (String) aMap.get((lastIdx > -1) ? fileName.substring(0, lastIdx) : fileName);
		}
		if (guid == null)	return null;		
	
		// turn off error reporting and see if guid exists in library
		boolean oldReport_Error = MultiFileResourceSetImpl.REPORT_ERROR;
		MultiFileResourceSetImpl.REPORT_ERROR = false;
		MethodElement e = LibraryService.getInstance().getCurrentLibraryManager()
				.getMethodElement(guid);
		MultiFileResourceSetImpl.REPORT_ERROR = oldReport_Error;
		if (e == null)
			return null;

		return guid;
	}
	
	/**
	 * get the file name with the given prefix and extension
	 * @param view Bookmark
	 * @param namePrefix String prefix for the name
	 * @param nameSuffix String suffix for the name
	 * @param ext String file extension, for example, ".html"
	 * @return String
	 */	 
	public String getFileName(Bookmark view, String namePrefix,
			String nameSuffix, String ext) {
		
		String existingElementName = null;
		StringBuffer buffer = new StringBuffer();
		if (namePrefix != null) {
			buffer.append(namePrefix);
		}
		
		if (view.getPresentationName() == "")
			return "0" + ext; //$NON-NLS-1$
		
		if (!gMap.isEmpty()) {
			existingElementName =  (String) gMap.get(view.getUniqueId());
		}
		// Browsing: Browsing CP with special chars failed with
		// blank pages and Script Error need to make a valid file name
		buffer.append((existingElementName != null) ? existingElementName : StrUtil.removeSpecialCharacters(view.getPresentationName()));
		if (nameSuffix != null) {
			buffer.append(nameSuffix);
		}

		if (ext != null) {
			if (ext.indexOf(".") < 0) //$NON-NLS-1$
			{
				ext = "." + ext; //$NON-NLS-1$
			}
			buffer.append(ext);
		}

		ElementFile a = new ElementFile(view.getUniqueId(), buffer.toString());
		
		if (a != null && aSet.add(a)) {
			int extDot = a.getFileName().lastIndexOf(".");
			aMap.put((extDot < 0) ? a.getFileName() : a.getFileName().substring(0, extDot), view.getUniqueId());			 
			gMap.put(view.getUniqueId(), (extDot < 0) ? a.getFileName() : a.getFileName().substring(0, extDot));
		}

		return a.getFileName(); 
	}
}
