/*
 * Copyright (c) 2017. tangzx(love.tangzx@qq.com)
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.tang.intellij.lua.editor;

import com.intellij.codeInsight.editorActions.enter.EnterHandlerDelegate;
import com.intellij.lang.ASTNode;
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.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.codeStyle.CodeStyleManager;
import com.intellij.psi.tree.IElementType;
import com.tang.intellij.lua.editor.completion.KeywordInsertHandler;
import com.tang.intellij.lua.psi.LuaIndentRange;
import com.tang.intellij.lua.psi.LuaTypes;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 * 回车时的自动补全
 * Created by tangzx on 2016/11/26.
 */
public class LuaEnterAfterUnmatchedBraceHandler implements EnterHandlerDelegate {

    private static IElementType getEnd(IElementType range) {
        if (range == LuaTypes.TABLE_EXPR)
            return LuaTypes.RCURLY;
        if (range == LuaTypes.REPEAT_STAT)
            return LuaTypes.UNTIL;
        return LuaTypes.END;
    }

    @Override
    public Result preprocessEnter(@NotNull PsiFile psiFile,
                                  @NotNull Editor editor,
                                  @NotNull Ref<Integer> caretOffsetRef,
                                  @NotNull Ref<Integer> caretAdvance,
                                  @NotNull DataContext dataContext,
                                  @Nullable EditorActionHandler editorActionHandler) {
        int caretOffset = caretOffsetRef.get();

        PsiElement element = psiFile.findElementAt(caretOffset - 1);
        if (element != null) {
            boolean needAddEnd = false;
            PsiElement range = null;
            PsiElement cur = element;
            while (true) {
                PsiElement searched = cur.getParent();
                if (searched == null || searched instanceof PsiFile) break;
                if (searched instanceof LuaIndentRange) {
                    IElementType endType = getEnd(searched.getNode().getElementType());
                    ASTNode endChild = searched.getNode().findChildByType(endType);
                    if (endChild == null) {
                        needAddEnd = true;
                        range = searched;
                        break;
                    }
                }
                cur = searched;
            }

            if (needAddEnd) {
                IElementType endType = getEnd(range.getNode().getElementType());
                Document document = editor.getDocument();
                document.insertString(caretOffset, "\n" + endType.toString());
                Project project = element.getProject();

                final TextRange textRange = range.getTextRange();
                PsiDocumentManager.getInstance(project).commitDocument(document);
                ApplicationManager.getApplication().runWriteAction(() -> {
                    CodeStyleManager styleManager = CodeStyleManager.getInstance(project);
                    styleManager.adjustLineIndent(psiFile, textRange);
                    KeywordInsertHandler.autoIndent(endType, psiFile, project, document, caretOffset);
                });
                return Result.Stop;
            }
        }

        return Result.Continue;
    }

    @Override
    public Result postProcessEnter(@NotNull PsiFile psiFile, @NotNull Editor editor, @NotNull DataContext dataContext) {
        return Result.Continue;
    }
}

@@ -1361,37 +1361,32 @@
 ype;%0Aimport com.
-tang.
 intellij.lua.edi
@@ -1382,50 +1382,28 @@
 lij.
-lua.editor.completion.KeywordInsertHandler
+psi.util.PsiTreeUtil
 ;%0Aim
@@ -3623,36 +3623,116 @@
     
-final Tex
+PsiDocumentManager.getInstance(project).commitDocument(document);%0A                LuaInden
 tRange 
-text
+new
 Range = 
 rang
@@ -3731,112 +3731,216 @@
 e = 
-range.getTextRange();%0A                PsiDocumentMana
+PsiTreeUtil.findElementOfClassAtOffset(psiFile, caretOffset, LuaIndentRange.class, false);%0A                if (newRange != null) %7B%0A                    final TextRange textRange = newRan
 ge
-r
 .get
-Instance(project).commitDocument(document);%0A
+TextRange();%0A    
     
@@ -4030,16 +4030,20 @@
         
+    
 CodeStyl
@@ -4125,16 +4125,20 @@
         
+    
 styleMan
@@ -4204,88 +4204,9 @@
     
-KeywordInsertHandler.autoIndent(endType, psiFile, project, document, caretOffset
+%7D
 );%0A 
@@ -4213,34 +4213,32 @@
                %7D
-);
 %0A               

fix adjust line indent bug #32