/*=============================================================================#
 # Copyright (c) 2008, 2017 Stephan Wahlbrink and others.
 # 
 # This program and the accompanying materials are made available under the
 # terms of the Eclipse Public License 2.0 which is available at
 # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
 # which is available at https://www.apache.org/licenses/LICENSE-2.0.
 # 
 # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
 # 
 # Contributors:
 #     Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
 #=============================================================================*/

package org.eclipse.statet.r.core.refactoring;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IRegion;
import org.eclipse.ltk.core.refactoring.Change;
import org.eclipse.ltk.core.refactoring.Refactoring;
import org.eclipse.ltk.core.refactoring.RefactoringStatus;
import org.eclipse.ltk.core.refactoring.TextFileChange;
import org.eclipse.osgi.util.NLS;
import org.eclipse.text.edits.ReplaceEdit;

import org.eclipse.statet.jcommons.collections.ImList;

import org.eclipse.statet.internal.r.core.refactoring.Messages;
import org.eclipse.statet.ltk.core.LTK;
import org.eclipse.statet.ltk.model.core.ElementSet;
import org.eclipse.statet.ltk.model.core.elements.ISourceUnit;
import org.eclipse.statet.ltk.refactoring.core.CommonRefactoringDescriptor;
import org.eclipse.statet.ltk.refactoring.core.RefactoringChange;
import org.eclipse.statet.ltk.refactoring.core.RefactoringMessages;
import org.eclipse.statet.ltk.refactoring.core.SourceUnitChange;
import org.eclipse.statet.ltk.refactoring.core.TextChangeCompatibility;
import org.eclipse.statet.ltk.refactoring.core.TextChangeManager;
import org.eclipse.statet.r.core.IRProject;
import org.eclipse.statet.r.core.RUtil;
import org.eclipse.statet.r.core.model.IRFrame;
import org.eclipse.statet.r.core.model.IRFrameInSource;
import org.eclipse.statet.r.core.model.IRModelInfo;
import org.eclipse.statet.r.core.model.IRModelManager;
import org.eclipse.statet.r.core.model.IRSourceUnit;
import org.eclipse.statet.r.core.model.IRWorkspaceSourceUnit;
import org.eclipse.statet.r.core.model.RElementAccess;
import org.eclipse.statet.r.core.model.RElementName;
import org.eclipse.statet.r.core.model.RModel;
import org.eclipse.statet.r.core.refactoring.RElementSearchProcessor.Mode;
import org.eclipse.statet.r.core.rlang.RTerminal;
import org.eclipse.statet.r.core.rsource.ast.NodeType;
import org.eclipse.statet.r.core.rsource.ast.RAst;
import org.eclipse.statet.r.core.rsource.ast.RAstNode;


public class RenameInWorkspaceRefactoring extends Refactoring {
	
	
	private static final int FOUND_NONE= 0;
	private static final int FOUND_READ= 1;
	private static final int FOUND_WRITE= 2;
	
	
	private class SearchProcessor extends RElementSearchProcessor {
		
		
		TextChangeManager changeManager;
		
		
		public SearchProcessor(final RElementName elementName,
				final IRSourceUnit sourceUnit, final RElementAccess mainAccess) {
			super(elementName, sourceUnit, mainAccess, null, WARN_NO_DEFINITION);
		}
		
		
		@Override
		public void begin(final SubMonitor m) {
			this.changeManager= new TextChangeManager();
		}
		
		@Override
		public void beginFinalProcessing(final SubMonitor m) {
			m.subTask(RefactoringMessages.Common_CreateChanges_label);
			
			final IRSourceUnit initialSu= getInitialSourceUnit();
			final TextFileChange textFileChange= this.changeManager.get(initialSu);
			if (initialSu.getWorkingContext() == LTK.EDITOR_CONTEXT) {
				textFileChange.setSaveMode(TextFileChange.LEAVE_DIRTY);
			}
		}
		
		@Override
		public void process(final IRProject project, final List<ISourceUnit> sus,
				final SubMonitor m) throws BadLocationException {
			if (sus != null) {
				int workRemaining= sus.size();
				for (final ISourceUnit su : sus) {
					m.setWorkRemaining(workRemaining--);
					final TextFileChange change= this.changeManager.get(su);
					createChanges(su, change, this.definitionFrameIds, m.newChild(1));
				}
			}
		}
		
	}
	
	
	private final RRefactoringAdapter adapter= new RRefactoringAdapter();
	private final ElementSet elementSet;
	
	private IRegion selectionRegion;
	
	private final IRWorkspaceSourceUnit sourceUnit;
	
	private RAstNode initialSymbolNode;
	private RElementAccess initialAccess;
	private SearchProcessor searchProcessor;
	
	private String newName;
	private Change[] changes;
	
	
	/**
	 * Creates a new rename refactoring
	 * 
	 * @param su the source unit
	 * @param region (selected) region of an occurrence of the variable
	 */
	public RenameInWorkspaceRefactoring(final IRWorkspaceSourceUnit su, final IRegion region) {
		this.sourceUnit= su;
		this.elementSet= new ElementSet(new Object[] { su });
		
		if (region != null && region.getOffset() >= 0 && region.getLength() >= 0) {
			this.selectionRegion= region;
		}
	}
	
	/**
	 * Creates a new rename refactoring
	 * 
	 * @param su the source unit
	 * @param region (selected) region of an occurrence of the variable
	 */
	public RenameInWorkspaceRefactoring(final IRWorkspaceSourceUnit su, final RAstNode node) {
		this.sourceUnit= su;
		this.elementSet= new ElementSet(new Object[] { su });
		
		if (node.getNodeType() == NodeType.SYMBOL || node.getNodeType() == NodeType.STRING_CONST) {
			this.initialSymbolNode= node;
		}
	}
	
	
	@Override
	public String getName() {
		return Messages.RenameInWorkspace_label;
	}
	
	public String getIdentifier() {
		return RRefactoring.RENAME_IN_WORKSPACE_REFACTORING_ID;
	}
	
	@Override
	public RefactoringStatus checkInitialConditions(final IProgressMonitor monitor) throws CoreException {
		final SubMonitor m= SubMonitor.convert(monitor, 6);
		try {
			if (this.selectionRegion != null) {
				this.initialSymbolNode= this.adapter.searchPotentialNameNode(this.sourceUnit, this.selectionRegion,
						false, m.newChild(4) );
				}
			if (this.initialSymbolNode == null) {
				return RefactoringStatus.createFatalErrorStatus(Messages.RenameInWorkspace_error_InvalidSelection_message);
			}
			if (this.sourceUnit.getResource() == null || this.sourceUnit.getResource().getProject() == null) {
				return RefactoringStatus.createFatalErrorStatus("The file is not in the workspace");
			}
			final RefactoringStatus result= new RefactoringStatus();
			this.adapter.checkInitialToModify(result, this.elementSet);
			if (result.hasFatalError()) {
				return result;
			}
			
			checkVariable(result);
			return result;
		}
		finally {
			m.done();
		}
	}
	
	private void checkVariable(final RefactoringStatus result) {
		this.initialAccess= RElementAccess.getMainElementAccessOfNameNode(this.initialSymbolNode);
		final RElementAccess subAccess= RElementAccess.getElementAccessOfNameNode(this.initialSymbolNode);
		final RElementName fullName= (this.initialAccess != null && subAccess != null) ?
				RElementName.create(this.initialAccess, subAccess.getNextSegment(), false) : null;
		this.searchProcessor= new SearchProcessor(fullName, this.sourceUnit, this.initialAccess);
		if (this.searchProcessor.getStatus().getSeverity() >= IStatus.ERROR) {
			result.merge(RefactoringStatus.create(this.searchProcessor.getStatus()));
			return;
		}
		
		this.newName= fullName.getDisplayName();
	}
	
	public String getCurrentName() {
		return this.searchProcessor.getElementName().getDisplayName();
	}
	
	public String getNewName() {
		return this.newName;
	}
	
	public RefactoringStatus checkNewName(final String name) {
		final String message= this.adapter.validateIdentifier(name, "The variable name");
		if (message != null) {
			return RefactoringStatus.createFatalErrorStatus(message);
		}
		return new RefactoringStatus();
	}
	
	public void setNewName(final String name) {
		this.newName= name;
	}
	
	public List<Mode> getAvailableModes() {
		return this.searchProcessor.getAvailableModes();
	}
	
	public Mode getMode() {
		return this.searchProcessor.getMode();
	}
	
	public void setMode(final Mode mode) {
		this.searchProcessor.setMode(mode);
	}
	
	@Override
	public RefactoringStatus checkFinalConditions(final IProgressMonitor monitor) throws CoreException {
		final SubMonitor m= SubMonitor.convert(monitor, RefactoringMessages.Common_FinalCheck_label, 20 + 3);
		try {
			final RefactoringStatus status= checkNewName(this.newName);
			if (status.getSeverity() >= IStatus.ERROR) {
				return status;
			}
			
			if (getMode() == Mode.LOCAL_FRAME) {
				this.changes= createLocalChanges(m.newChild(20));
				
				this.adapter.checkFinalToModify(status, this.elementSet, m.newChild(2));
				return status;
			}
			else {
				this.searchProcessor.run(m.newChild(20));
				if (this.searchProcessor.getStatus() != Status.OK_STATUS) {
					status.merge(RefactoringStatus.create(this.searchProcessor.getStatus()));
				}
				final TextChangeManager changeManager= this.searchProcessor.changeManager;
				this.changes= changeManager.getAllChanges();
				m.worked(1);
				
				final ElementSet elements= new ElementSet(changeManager.getAllSourceUnits());
				this.adapter.checkFinalToModify(status, elements, m.newChild(2));
				return status;
			}
		}
		finally {
			m.done();
		}
	}
	
	@Override
	public Change createChange(final IProgressMonitor monitor) throws CoreException {
		final SubMonitor m= SubMonitor.convert(monitor, RefactoringMessages.Common_CreateChanges_label, 3);
		try {
			final Map<String, String> arguments= new HashMap<>();
			final String description= NLS.bind(Messages.RenameInWorkspace_Descriptor_description,
					RUtil.formatVarName(getNewName()) );
			final IProject resource= this.elementSet.getSingleProject();
			final String project= (resource != null) ? resource.getName() : null;
			final String source= (project != null) ? NLS.bind(RefactoringMessages.Common_Source_Project_label, project) : RefactoringMessages.Common_Source_Workspace_label;
			final int flags= 0;
			final String comment= ""; //$NON-NLS-1$
			final CommonRefactoringDescriptor descriptor= new CommonRefactoringDescriptor(
					getIdentifier(), project, description, comment, arguments, flags);
			
			return new RefactoringChange(descriptor,
					Messages.RenameInWorkspace_label, 
					this.changes);
		}
		finally {
			m.done();
		}
	}
	
	
	private Change[] createLocalChanges(final SubMonitor m) {
		m.setWorkRemaining(2 + 4);
		
		final TextFileChange change= new SourceUnitChange(this.sourceUnit);
		if (this.sourceUnit.getWorkingContext() == LTK.EDITOR_CONTEXT) {
			change.setSaveMode(TextFileChange.LEAVE_DIRTY);
		}
		
		this.sourceUnit.connect(m.newChild(1));
		try {
			final ImList<? extends RElementAccess> accessList= this.initialAccess.getAllInUnit(false);
			
			final String unquoted= RRefactoringAdapter.getUnquotedIdentifier(this.newName);
			final String quoted= RRefactoringAdapter.getQuotedIdentifier(this.newName);
			final boolean isQuoted= (this.newName.charAt(0) == '`');
			
			for (final RElementAccess aAccess : accessList) {
				final RAstNode nameNode= aAccess.getNameNode();
				final String text= (isQuoted && nameNode.getNodeType() == NodeType.SYMBOL && nameNode.getOperator(0) == RTerminal.SYMBOL) ?
						this.newName : unquoted;
				final IRegion nameRegion= RAst.getElementNameRegion(nameNode);
				TextChangeCompatibility.addTextEdit(change, Messages.RenameInWorkspace_Changes_ReplaceOccurrence_name,
						new ReplaceEdit(nameRegion.getOffset(), nameRegion.getLength(), text));
			}
			m.worked(4);
			
			return new Change[] { change };
		}
		finally {
			this.sourceUnit.disconnect(m.newChild(1));
		}
	}
	
	
	private int createChanges(final ISourceUnit su, final TextFileChange change,
			final Set<String> definitionFrameIds, final SubMonitor m) throws BadLocationException {
		m.setWorkRemaining(3 + 6);
		
		int found= FOUND_NONE;
		su.connect(m.newChild(1));
		try {
			final IRModelInfo modelInfo= (IRModelInfo) su.getModelInfo(RModel.R_TYPE_ID,
					IRModelManager.MODEL_FILE, m.newChild(1) );
			
			final String unquoted= RRefactoringAdapter.getUnquotedIdentifier(this.newName);
			final String quoted= RRefactoringAdapter.getQuotedIdentifier(this.newName);
			final boolean isQuoted= (this.newName.charAt(0) == '`');
			
			final List<List<? extends RElementAccess>> allFrameAccess= new ArrayList<>();
			for (final String frameId : definitionFrameIds) {
				final IRFrame frame;
				if (frameId == null) {
					frame= modelInfo.getTopFrame();
				}
				else {
					frame= modelInfo.getReferencedFrames().get(frameId);
				}
				if (frame instanceof IRFrameInSource) {
					final List<? extends RElementAccess> allAccess= ((IRFrameInSource) frame).getAllAccessOf(
							this.searchProcessor.mainName.getSegmentName(), false );
					if (allAccess != null && allAccess.size() > 0) {
						allFrameAccess.add(allAccess);
					}
				}
			}
			m.worked(2);
			
			for (final List<? extends RElementAccess> allAccess : allFrameAccess) {
				for (final RElementAccess access : allAccess) {
					found|= (access.isWriteAccess() && access.getNextSegment() == null) ? FOUND_WRITE : FOUND_READ;
					final RAstNode nameNode= access.getNameNode();
					final String text= (isQuoted && nameNode.getNodeType() == NodeType.SYMBOL && nameNode.getOperator(0) == RTerminal.SYMBOL) ?
							this.newName : unquoted;
					final IRegion nameRegion= RAst.getElementNameRegion(nameNode);
					TextChangeCompatibility.addTextEdit(change, Messages.RenameInWorkspace_Changes_ReplaceOccurrence_name,
							new ReplaceEdit(nameRegion.getOffset(), nameRegion.getLength(), text));
				}
			}
			m.worked(4);
			
			return found;
		}
		finally {
			su.disconnect(m.newChild(1));
		}
	}
	
}
