//------------------------------------------------------------------------------
// 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);
		}
		
		if (existingElementName == null) {
			
			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();
		}
		return buffer.toString();
	}
	
	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(); 
	}
}
