///*
// * Copyright 2011 Jon S Akhtar (Sylvanaar)
// *
// * 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.sylvanaar.idea.Lua.editor.completion.smartEnter;
//
//import com.intellij.codeInsight.editorActions.smartEnter.EnterProcessor;
//import com.intellij.codeInsight.editorActions.smartEnter.SmartEnterProcessor;
//import com.intellij.openapi.actionSystem.IdeActions;
//import com.intellij.openapi.diagnostic.Logger;
//import com.intellij.openapi.editor.Document;
//import com.intellij.openapi.editor.Editor;
//import com.intellij.openapi.editor.RangeMarker;
//import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
//import com.intellij.openapi.editor.actionSystem.EditorActionManager;
//import com.intellij.openapi.editor.ex.EditorEx;
//import com.intellij.openapi.project.Project;
//import com.intellij.openapi.util.Key;
//import com.intellij.psi.PsiElement;
//import com.intellij.psi.PsiFile;
//import com.intellij.util.IncorrectOperationException;
//import com.sylvanaar.idea.Lua.editor.completion.smartEnter.processors.LuaPlainEnterProcessor;
//import org.jetbrains.annotations.NotNull;
//
//import java.util.ArrayList;
//import java.util.List;
//
///**
// * User: Dmitry.Krasilschikov
// * Date: 29.07.2008
// */
//public class LuaSmartEnterProcessor extends SmartEnterProcessor {
//
// private static final Logger LOG = Logger.getInstance("#org.jetbrains.plugins.groovy.lang.completion.smartEnter.GroovySmartEnterProcessor");
//
//// private static final GrFixer[] ourFixers;
// private static final EnterProcessor[] ourEnterProcessors;
//
// static {
//// final List<GrFixer> fixers = new ArrayList<GrFixer>();
//// fixers.add(new GrMissingIfStatement());
//// fixers.add(new GrIfConditionFixer());
//// fixers.add(new GrLiteralFixer());
//// fixers.add(new GrMethodCallFixer());
//// fixers.add(new GrMethodBodyFixer());
//// fixers.add(new GrMethodParametersFixer());
//// fixers.add(new GrWhileConditionFixer());
//// fixers.add(new GrWhileBodyFixer());
//// fixers.add(new GrForBodyFixer());
//// fixers.add(new GrListFixer());
////
//// ourFixers = fixers.toArray(new GrFixer[fixers.size()]);
//
// List<EnterProcessor> processors = new ArrayList<EnterProcessor>();
// processors.add(new LuaPlainEnterProcessor());
// ourEnterProcessors = processors.toArray(new EnterProcessor[processors.size()]);
// }
//
// private int myFirstErrorOffset = Integer.MAX_VALUE;
// private static final int MAX_ATTEMPTS = 20;
// private static final Key<Long> SMART_ENTER_TIMESTAMP = Key.create("smartEnterOriginalTimestamp");
//
// public static class TooManyAttemptsException extends Exception {
// }
//
// public boolean process(@NotNull final Project project, @NotNull final Editor editor, @NotNull final PsiFile psiFile) {
// final Document document = editor.getDocument();
// final String textForRollback = document.getText();
// try {
// editor.putUserData(SMART_ENTER_TIMESTAMP, editor.getDocument().getModificationStamp());
// myFirstErrorOffset = Integer.MAX_VALUE;
// process(project, editor, psiFile, 0);
// }
// catch (TooManyAttemptsException e) {
// document.replaceString(0, document.getTextLength(), textForRollback);
// } finally {
// editor.putUserData(SMART_ENTER_TIMESTAMP, null);
// }
// return true;
// }
//
//
// private void process(@NotNull final Project project, @NotNull final Editor editor, @NotNull final PsiFile file, final int attempt) throws TooManyAttemptsException {
// if (attempt > MAX_ATTEMPTS) throw new TooManyAttemptsException();
//
// try {
// commit(editor);
//// if (myFirstErrorOffset != Integer.MAX_VALUE) {
//// editor.getCaretModel().moveToOffset(myFirstErrorOffset);
//// }
////
//// myFirstErrorOffset = Integer.MAX_VALUE;
////
// PsiElement atCaret = getStatementAtCaret(editor, file);
//// if (atCaret == null) {
//// if (!new GroovyCommentBreakerEnterProcessor().doEnter(editor, file, false)) {
//// plainEnter(editor);
//// }
//// return;
//// }
////
//// List<PsiElement> queue = new ArrayList<PsiElement>();
//// collectAllElements(atCaret, queue, true);
//// queue.add(atCaret);
////
//// for (PsiElement psiElement : queue) {
//// for (GrFixer fixer : ourFixers) {
//// fixer.apply(editor, this, psiElement);
//// if (LookupManager.getInstance(project).getActiveLookup() != null) {
//// return;
//// }
//// if (isUncommited(project) || !psiElement.isValid()) {
//// moveCaretInsideBracesIfAny(editor, file);
//// process(project, editor, file, attempt + 1);
//// return;
//// }
//// }
//// }
//
// doEnter(atCaret, editor);
// }
// catch (IncorrectOperationException e) {
// LOG.error(e);
// }
// }
//
//// @Override
//// protected void reformat(PsiElement atCaret) throws IncorrectOperationException {
//// PsiElement parent = atCaret.getParent();
//// if (parent instanceof GrCodeBlock) {
//// final GrCodeBlock block = (GrCodeBlock) parent;
//// if (block.getStatements().length > 0 && block.getStatements()[0] == atCaret) {
//// atCaret = block;
//// }
//// } else if (parent instanceof GrForStatement) {
//// atCaret = parent;
//// }
////
//// super.reformat(atCaret);
//// }
//
//
// private void doEnter(PsiElement atCaret, Editor editor) throws IncorrectOperationException {
// final PsiFile psiFile = atCaret.getContainingFile();
//
// final RangeMarker rangeMarker = createRangeMarker(atCaret);
// if (myFirstErrorOffset != Integer.MAX_VALUE) {
// editor.getCaretModel().moveToOffset(myFirstErrorOffset);
// reformat(atCaret);
// return;
// }
//
// // reformat(atCaret);
// commit(editor);
//
// // atCaret = GroovyRefactoringUtil.findElementInRange(((GroovyFileBase) psiFile), rangeMarker.getStartOffset(), rangeMarker.getEndOffset(), atCaret.getClass());
//
//// atCaret = CodeInsightUtil.findElementInRange(psiFile, rangeMarker.getStartOffset(), rangeMarker.getEndOffset(), atCaret.getClass());
//
//
// for (EnterProcessor processor : ourEnterProcessors) {
// if (atCaret == null) {
// // Can't restore element at caret after enter processor execution!
// break;
// }
//
// if (processor.doEnter(editor, atCaret, isModified(editor))) return;
// }
//
// if (!isModified(editor)) {
// plainEnter(editor);
// } else {
// if (myFirstErrorOffset == Integer.MAX_VALUE) {
// editor.getCaretModel().moveToOffset(rangeMarker.getEndOffset());
// } else {
// editor.getCaretModel().moveToOffset(myFirstErrorOffset);
// }
// }
// }
//
//// private static void collectAllElements(PsiElement atCaret, List<PsiElement> res, boolean recurse) {
//// res.add(0, atCaret);
//// if (doNotStepInto(atCaret)) {
//// if (!recurse) return;
//// recurse = false;
//// }
////
//// PsiElement parent = atCaret.getParent();
//// if (atCaret instanceof GrClosableBlock && parent instanceof GrStringInjection && parent.getParent() instanceof GrString) {
//// res.add(parent.getParent());
//// }
////
//// if (parent instanceof GrArgumentList) {
//// res.add(parent.getParent());
//// }
////
//// //if (parent instanceof GrWhileStatement) {
//// // res.add(parent);
//// //}
////
//// final PsiElement[] children = getChildren(atCaret);
////
//// for (PsiElement child : children) {
//// if (atCaret instanceof GrStatement && child instanceof GrStatement) continue;
//// collectAllElements(child, res, recurse);
//// }
//// }
//
//// private static boolean doNotStepInto(PsiElement element) {
//// return element instanceof PsiClass || element instanceof GrCodeBlock || element instanceof GrStatement || element instanceof GrMethod;
//// }
//
//// @Nullable
//// protected PsiElement getStatementAtCaret(Editor editor, PsiFile psiFile) {
//// final PsiElement atCaret = super.getStatementAtCaret(editor, psiFile);
////
//// if (atCaret instanceof PsiWhiteSpace) return null;
//// if (atCaret == null) return null;
////
//// final GrCodeBlock codeBlock = PsiTreeUtil.getParentOfType(atCaret, GrCodeBlock.class, false, GrControlStatement.class);
//// if (codeBlock != null) {
//// for (GrStatement statement : codeBlock.getStatements()) {
//// if (PsiTreeUtil.isAncestor(statement, atCaret, true)) {
//// return statement;
//// }
//// }
//// }
////
//// PsiElement statementAtCaret = PsiTreeUtil.getParentOfType(atCaret,
//// GrStatement.class,
//// GrCodeBlock.class,
//// PsiMember.class,
//// GrDocComment.class
//// );
////
//// if (statementAtCaret instanceof GrBlockStatement) return null;
//// if (statementAtCaret == null) return null;
////
//// GrControlStatement controlStatement = PsiTreeUtil.getParentOfType(statementAtCaret, GrControlStatement.class, false);
////
//// if (controlStatement != null && !PsiTreeUtil.hasErrorElements(statementAtCaret)) {
//// return controlStatement;
//// }
////
//// return statementAtCaret instanceof GrStatement ||
//// statementAtCaret instanceof GrMember
//// ? statementAtCaret
//// : null;
//// }
//
//// protected void moveCaretInsideBracesIfAny(@NotNull final Editor editor, @NotNull final PsiFile file) throws IncorrectOperationException {
//// int caretOffset = editor.getCaretModel().getOffset();
//// final CharSequence chars = editor.getDocument().getCharsSequence();
////
//// if (CharArrayUtil.regionMatches(chars, caretOffset, "{}")) {
//// caretOffset += 2;
//// } else if (CharArrayUtil.regionMatches(chars, caretOffset, "{\n}")) {
//// caretOffset += 3;
//// }
////
//// caretOffset = CharArrayUtil.shiftBackward(chars, caretOffset - 1, " \t") + 1;
////
//// if (CharArrayUtil.regionMatches(chars, caretOffset - "{}".length(), "{}") ||
//// CharArrayUtil.regionMatches(chars, caretOffset - "{\n}".length(), "{\n}")) {
//// commit(editor);
//// final CodeStyleSettings settings = CodeStyleSettingsManager.getSettings(file.getProject());
//// final boolean old = settings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE;
//// settings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE = false;
//// PsiElement elt = PsiTreeUtil.getParentOfType(file.findElementAt(caretOffset - 1), GrCodeBlock.class);
//// reformat(elt);
//// settings.KEEP_SIMPLE_BLOCKS_IN_ONE_LINE = old;
//// editor.getCaretModel().moveToOffset(caretOffset - 1);
//// }
//// }
//
// public void registerUnresolvedError(int offset) {
// if (myFirstErrorOffset > offset) {
// myFirstErrorOffset = offset;
// }
// }
//
// protected static void plainEnter(@NotNull final Editor editor) {
// getEnterHandler().execute(editor, ((EditorEx) editor).getDataContext());
// }
//
// protected static EditorActionHandler getEnterHandler() {
// return EditorActionManager.getInstance().getActionHandler(IdeActions.ACTION_EDITOR_START_NEW_LINE);
// }
//
// protected static boolean isModified(@NotNull final Editor editor) {
// final Long timestamp = editor.getUserData(SMART_ENTER_TIMESTAMP);
// return editor.getDocument().getModificationStamp() != timestamp.longValue();
// }
//
//
// private static PsiElement[] getChildren(PsiElement element) {
// PsiElement psiChild = element.getFirstChild();
// if (psiChild == null) return new PsiElement[0];
//
// List<PsiElement> result = new ArrayList<PsiElement>();
// while (psiChild != null) {
// result.add(psiChild);
//
// psiChild = psiChild.getNextSibling();
// }
// return result.toArray(new PsiElement[result.size()]);
// }
//}