//------------------------------------------------------------------------------
// 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
//------------------------------------------------------------------------------
/**
 * Implementation for ITextReferenceReplacer. Used in deep copy
 * 
 * @author Weiping Lu
 *
 */
package org.eclipse.epf.library.util;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.regex.Matcher;

import org.eclipse.emf.ecore.EObject;
import org.eclipse.epf.library.LibraryPlugin;
import org.eclipse.epf.library.edit.util.ITextReferenceReplacer;
import org.eclipse.epf.persistence.MultiFileSaveUtil;
import org.eclipse.epf.uma.CapabilityPattern;
import org.eclipse.epf.uma.DeliveryProcess;
import org.eclipse.epf.uma.MethodElement;

public class TextReferenceReplacerImpl implements ITextReferenceReplacer {
	
	private static String CAPABILITY_PATH = MultiFileSaveUtil.CAPABILITY_PATTERN_PATH + "/";
	private static String DELIVERY_PATH = MultiFileSaveUtil.DELIVERY_PROCESS_PATH + "/";
	private static boolean debug = LibraryPlugin.getDefault().isDebugging();
	private final static boolean localDebug  = false;	
	
	private Map convertMap(Map oldToNewObjectMap) {
		if (oldToNewObjectMap == null) {
			if (localDebug) {
				System.out.println("LD> oldToNewObjectMap is null.");
			}
			return null;
		}
		Map m = null;
		Iterator it = oldToNewObjectMap.entrySet().iterator();
		while (it.hasNext()) {
			Map.Entry entry = (Map.Entry) it.next();
			Object key = entry.getKey();
			Object val = entry.getValue();
			if (localDebug) {
				System.out.println("LD> old key = " + key);
				System.out.println("LD> old val = " + val);
			}
			if ( key instanceof MethodElement && val instanceof MethodElement) {
				String newKey = ((MethodElement)key).getGuid();
				String newVal = ((MethodElement)val).getGuid();
				if (key != null && val != null) {
					if (m == null) {
						m = new HashMap();
					}
					m.put(newKey, newVal);
				}
				if (localDebug) {
					System.out.println("LD> new key = " + newKey + ", newVal = " + newVal);
					System.out.println("");
				}
			} 
		}
		return m;
	}

	public String replace(String source, EObject owner, Map oldToNewObjectMap) {
		if (localDebug) {
			System.out.println("LD> Entering TextReferenceReplacerImpl.replace: " + source);
			System.out.println("LD> owner: " + owner);
		}
		String ret = replace_(source, owner, oldToNewObjectMap);
		if (localDebug) {
			boolean noChange = ! source.equals(ret);
			String str = source.equals(ret) ? "No chnange!" : ret;
			System.out.println("LD> Exiting TextReferenceReplacerImpl.replace: " + str);
			System.out.println("");
		}
		return ret;
	}
	
	private String replace_(String source, EObject owner, Map oldToNewObjectMap) {	
		Map localMap = convertMap(oldToNewObjectMap);
		if (localMap == null) {
			return source;
		}
		
		String replacingPath = null;
		String replacedPath = null;			
		if (owner instanceof DeliveryProcess) {
			replacingPath = DELIVERY_PATH;
			replacedPath = CAPABILITY_PATH;
		}
		else if (owner instanceof CapabilityPattern) {
			replacingPath = CAPABILITY_PATH;
			replacedPath = DELIVERY_PATH;
		} else {
			replacingPath = "";
			replacedPath = "";
		}
		
		StringBuffer sb = new StringBuffer();
		Matcher m = ResourceHelper.p_link_ref.matcher(source);

		while (m.find()) {
			String text = m.group();						
			Map attributeMap = ResourceHelper.getAttributesFromLink(text);
			String oldGuid = (String) attributeMap.get(ResourceHelper.TAG_ATTR_GUID);	
			String newGuid = oldGuid == null ? null : (String) localMap.get(oldGuid);
			
			if (localDebug) {
				System.out.println("LD> text:      " + text);
				System.out.println("LD> attributeMap: " + attributeMap);
				System.out.println("LD> oldGuid: " + oldGuid);
				System.out.println("LD> newGuid: " + newGuid);
			}			
			if (newGuid != null && !newGuid.equals(oldGuid)) {
								
				//String replacement = text.replaceAll(oldGuid, newGuid);
				//Can't use the above commented out line, because some guid strings are not valid regex patterns
				String replacement = replaceAll(text, oldGuid, newGuid);		
				if (replacement.indexOf(replacedPath) > 0) {
					replacement = replacement.replaceFirst(replacedPath, replacingPath);
				}
				if (localDebug) {
					System.out.println("LD> replacement: " + replacement);
				}
				m.appendReplacement(sb, replacement);	
			}
			
		}
		m.appendTail(sb);
		return sb.toString();
	}
	
	public static String replaceAll(String text, String replaced, String replacing) {
		int fromIndex = 0;
		int ix = text.indexOf(replaced, fromIndex);
		if (ix < 0) {
			return text;
		}			
		int replacedLen = replaced.length();
		StringBuffer newText = new StringBuffer();
		while (ix >= fromIndex) {
			if (ix > fromIndex) {
				newText.append(text.substring(fromIndex, ix));
			}
			newText.append(replacing);
			fromIndex = ix + replacedLen;
			ix = text.indexOf(replaced, fromIndex);
		}
		if (fromIndex < text.length() ) {
			newText.append(text.substring(fromIndex, text.length()));
		}
		return newText.toString();
	}

}
