package com.siberika.idea.pascal.ide.actions;
import com.intellij.codeInsight.intention.LowPriorityAction;
import com.intellij.codeInsight.intention.impl.BaseIntentionAction;
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.util.IncorrectOperationException;
import com.siberika.idea.pascal.lang.PascalImportOptimizer;
import com.siberika.idea.pascal.lang.psi.PasUsesClause;
import com.siberika.idea.pascal.lang.psi.PascalQualifiedIdent;
import com.siberika.idea.pascal.util.DocUtil;
import com.siberika.idea.pascal.util.PsiUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
import java.util.List;
import static com.intellij.openapi.actionSystem.ActionPlaces.EDITOR_POPUP;
/**
* Author: George Bakhtadze
* Date: 21/12/2015
*/
public class UsesActions {
public static class ExcludeUnitAction extends BaseUsesUnitAction {
public ExcludeUnitAction(String name, PascalQualifiedIdent usedUnitName) {
super(name, usedUnitName);
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
final Document doc = PsiDocumentManager.getInstance(usedUnitName.getProject()).getDocument(usedUnitName.getContainingFile());
if (doc != null) {
doc.insertString(usedUnitName.getTextRange().getStartOffset(), "{!}");
PsiDocumentManager.getInstance(project).commitDocument(doc);
}
}
}
public static class OptimizeUsesAction extends BaseUsesAction implements LowPriorityAction {
public OptimizeUsesAction(String name) {
super(name);
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
PascalImportOptimizer.doProcess(file).run();
}
}
public static class MoveUnitAction extends BaseUsesUnitAction {
public MoveUnitAction(String name, PascalQualifiedIdent usedUnitName) {
super(name, usedUnitName);
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
TextRange range = getRangeToRemove();
if (range != null) {
final Document doc = PsiDocumentManager.getInstance(usedUnitName.getProject()).getDocument(usedUnitName.getContainingFile());
if (doc != null) {
PascalImportOptimizer.addUnitToSection(PsiUtil.getElementPasModule(file), Collections.singletonList(usedUnitName.getName()), false);
doc.deleteString(range.getStartOffset(), range.getEndOffset());
PsiDocumentManager.getInstance(project).commitDocument(doc);
}
}
}
}
public static class AddUnitAction extends BaseUsesAction {
private final String unitName;
private final boolean toInterface;
public AddUnitAction(String name, String unitName, boolean toInterface) {
super(name);
this.unitName = unitName;
this.toInterface = toInterface;
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
PascalImportOptimizer.addUnitToSection(PsiUtil.getElementPasModule(file), Collections.singletonList(unitName), toInterface);
}
}
public static class NewUnitAction extends BaseUsesAction {
private final String unitName;
public NewUnitAction(String name, String unitName) {
super(name);
this.unitName = unitName;
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
final DataContext dataContext = DataManager.getInstance().getDataContext(editor.getComponent());
final CreateModuleAction act = new CreateModuleAction();
final AnActionEvent ev = AnActionEvent.createFromAnAction(act, null, EDITOR_POPUP, dataContext);
ApplicationManager.getApplication().invokeLater(new Runnable() {
@Override
public void run() {
act.actionPerformed(ev);
}
});
}
}
public static class RemoveUnitAction extends BaseUsesUnitAction {
public RemoveUnitAction(String name, PascalQualifiedIdent usedUnitName) {
super(name, usedUnitName);
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
TextRange range = getRangeToRemove();
if (range != null) {
final Document doc = PsiDocumentManager.getInstance(usedUnitName.getProject()).getDocument(usedUnitName.getContainingFile());
if (doc != null) {
doc.deleteString(range.getStartOffset(), range.getEndOffset());
PsiDocumentManager.getInstance(project).commitDocument(doc);
}
}
}
}
private static abstract class BaseUsesUnitAction extends BaseUsesAction {
protected final PascalQualifiedIdent usedUnitName;
public BaseUsesUnitAction(String name, PascalQualifiedIdent usedUnitName) {
super(name);
this.usedUnitName = usedUnitName;
}
protected TextRange getRangeToRemove() {
PasUsesClause usesClause = (PasUsesClause) usedUnitName.getParent();
List<TextRange> ranges = PascalImportOptimizer.getUnitRanges(usesClause);
TextRange res = PascalImportOptimizer.removeUnitFromSection(usedUnitName, usesClause, ranges, usesClause.getNamespaceIdentList().size());
if ((res != null) && (usesClause.getNamespaceIdentList().size() == 1)) { // Remove whole uses clause if last unit removed
final Document doc = PsiDocumentManager.getInstance(usedUnitName.getProject()).getDocument(usedUnitName.getContainingFile());
res = TextRange.create(usesClause.getTextRange().getStartOffset(), DocUtil.expandRangeEnd(doc, usesClause.getTextRange().getEndOffset(), DocUtil.RE_LF));
}
return res;
}
}
private static abstract class BaseUsesAction extends BaseIntentionAction {
private final String name;
private BaseUsesAction(String name) {
this.name = name;
}
@Nls
@NotNull
@Override
public String getFamilyName() {
return "Pascal";
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return true;
}
@NotNull
@Override
public String getText() {
return name;
}
}
}