/*******************************************************************************
 * Copyright (c) 2004, 2013 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 API and implementation
 *******************************************************************************/
package org.aspectj.org.eclipse.jdt.core.dom;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;

import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.text.edits.TextEdit;

import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.TextUtilities;

import org.aspectj.org.eclipse.jdt.core.JavaCore;
import org.aspectj.org.eclipse.jdt.core.dom.SimplePropertyDescriptor;
import org.aspectj.org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
import org.aspectj.org.eclipse.jdt.core.dom.rewrite.TargetSourceRangeComputer;
import org.aspectj.org.eclipse.jdt.internal.compiler.parser.RecoveryScannerData;
import org.aspectj.org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer;
import org.aspectj.org.eclipse.jdt.internal.core.dom.rewrite.LineInformation;
import org.aspectj.org.eclipse.jdt.internal.core.dom.rewrite.ListRewriteEvent;
import org.aspectj.org.eclipse.jdt.internal.core.dom.rewrite.NodeInfoStore;
import org.aspectj.org.eclipse.jdt.internal.core.dom.rewrite.NodeRewriteEvent;
import org.aspectj.org.eclipse.jdt.internal.core.dom.rewrite.RewriteEventStore;
import org.aspectj.org.eclipse.jdt.internal.core.dom.rewrite.RewriteEventStore.CopySourceInfo;
import org.aspectj.org.eclipse.jdt.internal.core.dom.rewrite.RewriteEventStore.PropertyLocation;

/**
 * Internal class: not intended to be used by client.
 * When AST modifications recording is enabled, all changes are recorded by this class.
 */
@SuppressWarnings({"rawtypes", "unchecked"})
class InternalASTRewrite extends NodeEventHandler {

	/** root node for the rewrite: Only nodes under this root are accepted */
	private CompilationUnit root;

	protected final RewriteEventStore eventStore;
	protected final NodeInfoStore nodeStore;
	/** ASTNode clone -> ASTNode original */ 
	protected final Hashtable clonedNodes;

	int cloneDepth = 0;

	/**
	 * Constructor
	 * @param root root node of the recorded ast.
	 */
	public InternalASTRewrite(CompilationUnit root) {
		this.root = root;
		this.eventStore = new RewriteEventStore();
		this.nodeStore = new NodeInfoStore(root.getAST());
		this.clonedNodes = new Hashtable();
	}

	/**
	 * Performs the rewrite: The rewrite events are translated to the corresponding in text changes.
	 * The given options can be null in which case the global options {@link JavaCore#getOptions() JavaCore.getOptions()}
	 * will be used.
	 *
	 * @param document Document which describes the code of the AST that is passed in in the
	 * constructor. This document is accessed read-only.
	 * @param options the given options
	 * @throws IllegalArgumentException if the rewrite fails
	 * @return Returns the edit describing the text changes.
	 */
	public TextEdit rewriteAST(IDocument document, Map options) {
		TextEdit result = new MultiTextEdit();

		final CompilationUnit rootNode = getRootNode();
		if (rootNode != null) {
			TargetSourceRangeComputer xsrComputer = new TargetSourceRangeComputer() {
				/**
				 * This implementation of
				 * {@link TargetSourceRangeComputer#computeSourceRange(ASTNode)}
				 * is specialized to work in the case of internal AST rewriting, where the
				 * original AST has been modified from its original form. This means that
				 * one cannot trust that the root of the given node is the compilation unit.
				 */
				@Override
				public SourceRange computeSourceRange(ASTNode node) {
					int extendedStartPosition = rootNode.getExtendedStartPosition(node);
					int extendedLength = rootNode.getExtendedLength(node);
					return new SourceRange(extendedStartPosition, extendedLength);
				}
			};
			char[] content= document.get().toCharArray();
			LineInformation lineInfo= LineInformation.create(document);
			String lineDelim= TextUtilities.getDefaultLineDelimiter(document);
			List comments= rootNode.getCommentList();

			// MERGECONFLICT
			// AspectJ Extension - use the factory instead of building one directly
			// old code:
			// ASTRewriteAnalyzer visitor = new ASTRewriteAnalyzer(content, lineInfo, lineDelim, result, this.eventStore, this.nodeStore, comments, options, xsrComputer);
			// new code:
//			ASTVisitor visitor = ASTRewriteAnalyzer.getAnalyzerVisitor(content, lineInfo, lineInfoneDelim, result, this.eventStore, this.nodeStore, comments, options, xsrComputer);
			// End AspectJ Extension
			
			Map currentOptions = options == null ? JavaCore.getOptions() : options;
			// OLD
//			ASTRewriteAnalyzer visitor = new ASTRewriteAnalyzer(content, lineInfo, lineDelim, result, this.eventStore, this.nodeStore, comments, currentOptions, xsrComputer, (RecoveryScannerData)rootNode.getStatementsRecoveryData());
			
			// NEW  CAST NEEDED???
			ASTRewriteAnalyzer visitor = (ASTRewriteAnalyzer) ASTRewriteAnalyzer.getAnalyzerVisitor(content, lineInfo, lineDelim, result, this.eventStore, this.nodeStore, comments, currentOptions, xsrComputer, (RecoveryScannerData)rootNode.getStatementsRecoveryData());
			rootNode.accept(visitor);
		}
		return result;
	}

	private  void markAsMoveOrCopyTarget(ASTNode node, ASTNode newChild) {
		if (this.cloneDepth == 0) {
			while (node != null && this.clonedNodes.containsKey(node)) {
				/*
				 * A modified node cannot be considered as cloned any more.
				 * we can't copy the original formatting/comments and at the same time modify the node.
				 * 
				 * Workaround for https://bugs.eclipse.org/405699 is to remove such nodes from clonedNodes
				 * and instead mark all children as cloned (or skip them if they are not in clonedNodes).
				 */
				ASTNode orig = (ASTNode) this.clonedNodes.remove(node);
				if (orig != null) {
					List properties = node.structuralPropertiesForType();
					for (int i= 0; i < properties.size(); i++) {
						StructuralPropertyDescriptor property = (StructuralPropertyDescriptor) properties.get(i);
						Object child = node.getStructuralProperty(property);
						if (child instanceof ASTNode) {
							markAsMoveOrCopyTarget(node, (ASTNode) child);
						} else if (child instanceof List) {
							List children = (List) child;
							for (int j= 0; j < children.size(); j++) {
								ASTNode clonedChild = (ASTNode) children.get(j);
								markAsMoveOrCopyTarget(node, clonedChild);
							}
						}
					}
				}
				
				node = node.getParent();
			}
		}
		
		ASTNode source = (ASTNode)this.clonedNodes.get(newChild);
		if(source != null) {
			if(this.cloneDepth == 0) {
				PropertyLocation propertyLocation = this.eventStore.getPropertyLocation(source, RewriteEventStore.ORIGINAL);
				CopySourceInfo sourceInfo =
					this.eventStore.markAsCopySource(
						propertyLocation.getParent(),
						propertyLocation.getProperty(),
						source,
						false);
				this.nodeStore.markAsCopyTarget(newChild, sourceInfo);
			}
		} else if((newChild.getFlags() & ASTNode.ORIGINAL) != 0) {
			PropertyLocation propertyLocation = this.eventStore.getPropertyLocation(newChild, RewriteEventStore.ORIGINAL);
			CopySourceInfo sourceInfo =
				this.eventStore.markAsCopySource(
					propertyLocation.getParent(),
					propertyLocation.getProperty(),
					newChild,
					true);
			this.nodeStore.markAsCopyTarget(newChild, sourceInfo);
		}
	}

	private CompilationUnit getRootNode() {
		return this.root;
	}

	@Override
	public String toString() {
		StringBuffer buf = new StringBuffer();
		buf.append("Events:\n"); //$NON-NLS-1$
		buf.append(this.eventStore.toString());
		return buf.toString();
	}

	@Override
	void preValueChangeEvent(ASTNode node, SimplePropertyDescriptor property) {
		// force event creation
		getNodeEvent(node, property);
	}

	@Override
	void postValueChangeEvent(ASTNode node, SimplePropertyDescriptor property) {
		NodeRewriteEvent event = getNodeEvent(node, property);
		event.setNewValue(node.getStructuralProperty(property));
	}

	@Override
	void preAddChildEvent(ASTNode node, ASTNode child,	StructuralPropertyDescriptor property) {
		if(property.isChildProperty()) {
			NodeRewriteEvent event = getNodeEvent(node, property);
			event.setNewValue(child);
			if(child != null) {
				markAsMoveOrCopyTarget(node, child);
			}
		} else if(property.isChildListProperty()) {
			// force event creation
			getListEvent(node, property);
		}
	}

	@Override
	void postAddChildEvent(ASTNode node, ASTNode child,	StructuralPropertyDescriptor property) {
		if(property.isChildListProperty()) {

			ListRewriteEvent event = getListEvent(node, property);
			List list = (List)node.getStructuralProperty(property);
			int i = list.indexOf(child);
			int s = list.size();
			int index;
			if(i + 1 < s) {
				ASTNode nextNode = (ASTNode)list.get(i + 1);
				index = event.getIndex(nextNode, ListRewriteEvent.NEW);
			} else {
				index = -1;
			}
			event.insert(child, index);
			if(child != null) {
				markAsMoveOrCopyTarget(node, child);
			}
		}
	}

	@Override
	void preRemoveChildEvent(ASTNode node, ASTNode child, StructuralPropertyDescriptor property) {
		if(property.isChildProperty()) {
			NodeRewriteEvent event = getNodeEvent(node, property);
			event.setNewValue(null);
		} else if(property.isChildListProperty()) {
			ListRewriteEvent event = getListEvent(node, property);
			int i = event.getIndex(child, ListRewriteEvent.NEW);
			NodeRewriteEvent nodeEvent = (NodeRewriteEvent)event.getChildren()[i];
			if(nodeEvent.getOriginalValue() == null) {
				event.revertChange(nodeEvent);
			} else {
				nodeEvent.setNewValue(null);
			}
		}
	}

	@Override
	void preReplaceChildEvent(ASTNode node, ASTNode child, ASTNode newChild, StructuralPropertyDescriptor property) {
		if(property.isChildProperty()) {
			NodeRewriteEvent event = getNodeEvent(node, property);
			event.setNewValue(newChild);
			if(newChild != null) {
				markAsMoveOrCopyTarget(node, newChild);
			}
		} else if(property.isChildListProperty()) {
			ListRewriteEvent event = getListEvent(node, property);
			int i = event.getIndex(child, ListRewriteEvent.NEW);
			NodeRewriteEvent nodeEvent = (NodeRewriteEvent)event.getChildren()[i];
			nodeEvent.setNewValue(newChild);
			if(newChild != null) {
				markAsMoveOrCopyTarget(node, newChild);
			}
		}
	}


	@Override
	void preCloneNodeEvent(ASTNode node) {
		this.cloneDepth++;
	}


	@Override
	void postCloneNodeEvent(ASTNode node, ASTNode clone) {
		if(node.ast == this.root.ast && clone.ast == this.root.ast) {
			if((node.getFlags() & ASTNode.ORIGINAL) != 0) {
				this.clonedNodes.put(clone, node);
			} else {
				// node can be a cloned node
				Object original = this.clonedNodes.get(node);
				if(original != null) {
					this.clonedNodes.put(clone, original);
				}
			}
		}
		this.cloneDepth--;
	}

	private NodeRewriteEvent getNodeEvent(ASTNode node, StructuralPropertyDescriptor property) {
		return this.eventStore.getNodeEvent(node, property, true);
	}

	private ListRewriteEvent getListEvent(ASTNode node, StructuralPropertyDescriptor property) {
		return this.eventStore.getListEvent(node, property, true);
	}
}
