package org.antlr.intellij.plugin.validation;

import com.intellij.codeInspection.LocalQuickFixAndIntentionActionOnPsiElement;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.SmartPointerManager;
import com.intellij.psi.SmartPsiElementPointer;
import org.antlr.intellij.plugin.psi.LexerRuleRefNode;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.Objects;
import java.util.stream.Collectors;

class AddTokenDefinitionFix extends LocalQuickFixAndIntentionActionOnPsiElement {

    private final SmartPsiElementPointer<LexerRuleRefNode> smartPsiElementPointer;

    AddTokenDefinitionFix(LexerRuleRefNode element) {
        super(element);
        smartPsiElementPointer = SmartPointerManager.getInstance(element.getProject()).createSmartPsiElementPointer(Objects.requireNonNull(element));
    }

    @Nls(capitalization = Nls.Capitalization.Sentence)
    @NotNull
    @Override
    public String getFamilyName() {
        return "ANTLR4";
    }

    @NotNull
    @Override
    public String getText() {
        return "Add token definition built from letter fragments.";
    }

    @Override
    public void invoke(@NotNull Project project, @NotNull PsiFile file, @Nullable("is null when called from inspection") Editor editor, @NotNull PsiElement startElement, @NotNull PsiElement endElement) {
        appendTokenDefAtLastLine(editor);
    }

    private void appendTokenDefAtLastLine(@Nullable("is null when called from inspection") Editor editor) {
        String tokenName = smartPsiElementPointer.getElement().getReference().getCanonicalText();
        int lastLineOffset = editor.getDocument().getLineEndOffset(editor.getDocument().getLineCount() - 1);
        editor.getDocument().insertString(lastLineOffset, "\n" + buildTokenDefinitionText(tokenName));
    }

    @NotNull
    static String buildTokenDefinitionText(String tokenName) {
        String tokenDefRule = tokenName.toUpperCase().chars().mapToObj(c -> (char) c).map(String::valueOf).collect(Collectors.joining(" "));
        return tokenName + " : " + tokenDefRule + ";";
    }
}

@@ -71,32 +71,32 @@
 eIns
-pection.LocalQuickFixAnd
+ight.intention.impl.Base
 Inte
@@ -106,28 +106,16 @@
 onAction
-OnPsiElement
 ;%0Aimport
@@ -220,22 +220,30 @@
 lij.
-psi.PsiElement
+openapi.util.TextRange
 ;%0Aim
@@ -297,134 +297,40 @@
 lij.
-psi.SmartPointerManager;%0Aimport com.intellij.psi.SmartPsiElementPointer;%0Aimport org.antlr.intellij.plugin.psi.LexerRuleRefNode
+util.IncorrectOperationException
 ;%0Aim
@@ -514,16 +514,23 @@
 ctors;%0A%0A
+public 
 class Ad
@@ -561,24 +561,12 @@
 nds 
-LocalQuickFixAnd
+Base
 Inte
@@ -580,20 +580,8 @@
 tion
-OnPsiElement
  %7B%0A%0A
@@ -602,77 +602,40 @@
 nal 
-SmartPsiElementPointer%3CLexerRuleRefNode%3E smartPsiElementPointer
+TextRange textRange
 ;%0A%0A   
+ public
  Add
@@ -657,176 +657,56 @@
 Fix(
-LexerRuleRefNode element) %7B%0A        super(element);%0A        smartPsiElementPointer = SmartPointerManager.getInstance(element.getProject()).createSmartPsiElementPointer(
+TextRange textRange) %7B%0A        this.textRange = 
 Obje
@@ -728,16 +728,17 @@
 ull(
-element)
+textRange
 );%0A 
@@ -889,37 +889,24 @@
 R4%22;%0A    %7D%0A%0A
-    @NotNull%0A
     @Overrid
@@ -922,93 +922,104 @@
 lic 
-String getText() %7B%0A        return %22Add token definition built from letter fragments.%22
+boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) %7B%0A        return true
 ;%0A  
@@ -1090,203 +1090,246 @@
 ct, 
-@NotNull PsiFile file, @Nullable(%22is null when called from inspection%22) Editor editor, @NotNull PsiElement startElement, @NotNull PsiElement endElement) %7B%0A        appendTokenDefAtLastLine(editor)
+Editor editor, PsiFile file) throws IncorrectOperationException %7B%0A        appendTokenDefAtLastLine(editor);%0A    %7D%0A%0A    @NotNull%0A    @Override%0A    public String getText() %7B%0A        return %22Add token definition built from letter fragments.%22
 ;%0A  
@@ -1472,37 +1472,22 @@
 e = 
-smartPsiElementPointe
+edito
 r.get
-Ele
+Docu
 ment
@@ -1496,37 +1496,22 @@
 .get
-Reference().getCanonicalText(
+Text(textRange
 );%0A 

Simplify AddTokenDefinitionFix