/*
 * Copyright 2000-2009 JetBrains s.r.o.
 *
 * 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.intellij.codeInsight.editorActions.smartEnter;

import com.intellij.codeInsight.CodeInsightUtil;
import com.intellij.codeInsight.lookup.LookupManager;
import com.intellij.featureStatistics.FeatureUsageTracker;
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.*;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.text.CharArrayUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.util.ArrayList;
import java.util.List;

/**
 * @author spleaner
 */
public class JavaSmartEnterProcessor extends SmartEnterProcessor {
  private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.editorActions.smartEnter.JavaSmartEnterProcessor");

  private static final Fixer[] ourFixers;
  private static final EnterProcessor[] ourEnterProcessors = {
    new CommentBreakerEnterProcessor(),
    new AfterSemicolonEnterProcessor(),
    new LeaveCodeBlockEnterProcessor(),
    new PlainEnterProcessor()
  };
  private static final EnterProcessor[] ourAfterCompletionEnterProcessors = {
    new AfterSemicolonEnterProcessor(),
    new EnterProcessor() {
      @Override
      public boolean doEnter(Editor editor, PsiElement psiElement, boolean isModified) {
        return PlainEnterProcessor.expandCodeBlock(editor, psiElement);
      }
    }
  };

  static {
    final List<Fixer> fixers = new ArrayList<Fixer>();
    fixers.add(new LiteralFixer());
    fixers.add(new MethodCallFixer());
    fixers.add(new IfConditionFixer());
    fixers.add(new ForStatementFixer());
    fixers.add(new WhileConditionFixer());
    fixers.add(new CatchDeclarationFixer());
    fixers.add(new SwitchExpressionFixer());
    fixers.add(new CaseColonFixer());
    fixers.add(new DoWhileConditionFixer());
    fixers.add(new BlockBraceFixer());
    fixers.add(new MissingIfBranchesFixer());
    fixers.add(new MissingWhileBodyFixer());
    fixers.add(new MissingSwitchBodyFixer());
    fixers.add(new MissingCatchBodyFixer());
    fixers.add(new MissingSynchronizedBodyFixer());
    fixers.add(new MissingForBodyFixer());
    fixers.add(new MissingForeachBodyFixer());
    fixers.add(new ParameterListFixer());
    fixers.add(new MissingMethodBodyFixer());
    fixers.add(new MissingClassBodyFixer());
    fixers.add(new MissingReturnExpressionFixer());
    fixers.add(new MissingThrowExpressionFixer());
    fixers.add(new ParenthesizedFixer());
    fixers.add(new SemicolonFixer());
    fixers.add(new MissingArrayInitializerBraceFixer());
    fixers.add(new MissingArrayConstructorBracketFixer());
    fixers.add(new EnumFieldFixer());
    ourFixers = fixers.toArray(new Fixer[fixers.size()]);
  }

  private int myFirstErrorOffset = Integer.MAX_VALUE;
  private boolean mySkipEnter;
  private static final int MAX_ATTEMPTS = 20;
  private static final Key<Long> SMART_ENTER_TIMESTAMP = Key.create("smartEnterOriginalTimestamp");

  public static class TooManyAttemptsException extends Exception {}
  
  private final JavadocFixer myJavadocFixer = new JavadocFixer();

  @Override
  public boolean process(@NotNull final Project project, @NotNull final Editor editor, @NotNull final PsiFile psiFile) {
    FeatureUsageTracker.getInstance().triggerFeatureUsed("codeassists.complete.statement");

    return invokeProcessor(editor, psiFile, false);
  }

  @Override
  public boolean processAfterCompletion(@NotNull Editor editor, @NotNull PsiFile psiFile) {
    return invokeProcessor(editor, psiFile, true);
  }

  private boolean invokeProcessor(Editor editor, PsiFile psiFile, boolean afterCompletion) {
    final Document document = editor.getDocument();
    final CharSequence textForRollback = document.getImmutableCharSequence();
    try {
      editor.putUserData(SMART_ENTER_TIMESTAMP, editor.getDocument().getModificationStamp());
      myFirstErrorOffset = Integer.MAX_VALUE;
      mySkipEnter = false;
      process(editor, psiFile, 0, afterCompletion);
    }
    catch (TooManyAttemptsException e) {
      document.replaceString(0, document.getTextLength(), textForRollback);
    } finally {
      editor.putUserData(SMART_ENTER_TIMESTAMP, null);
    }
    return true;
  }

  private void process(@NotNull final Editor editor, @NotNull final PsiFile file, final int attempt, boolean afterCompletion) 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 (myJavadocFixer.process(editor, file)) {
          return;
        }
        if (!new CommentBreakerEnterProcessor().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 (Fixer fixer : ourFixers) {
          fixer.apply(editor, this, psiElement);
          if (LookupManager.getInstance(file.getProject()).getActiveLookup() != null) {
            return;
          }
          if (isUncommited(file.getProject()) || !psiElement.isValid()) {
            moveCaretInsideBracesIfAny(editor, file);
            process(editor, file, attempt + 1, afterCompletion);
            return;
          }
        }
      }

      doEnter(atCaret, editor, afterCompletion);
    }
    catch (IncorrectOperationException e) {
      LOG.error(e);
    }
  }


  @Override
  protected void reformat(PsiElement atCaret) throws IncorrectOperationException {
    if (atCaret == null) {
      return;
    }
    PsiElement parent = atCaret.getParent();
    if (parent instanceof PsiCodeBlock) {
      final PsiCodeBlock block = (PsiCodeBlock) parent;
      if (block.getStatements().length > 0 && block.getStatements()[0] == atCaret) {
        atCaret = block;
      }
    }
    else if (parent instanceof PsiForStatement) {
      atCaret = parent;
    }

    super.reformat(atCaret);
  }


  private void doEnter(PsiElement atCaret, Editor editor, boolean afterCompletion) 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);

    if (mySkipEnter) {
      return;
    }
    
    atCaret = CodeInsightUtil.findElementInRange(psiFile, rangeMarker.getStartOffset(), rangeMarker.getEndOffset(), atCaret.getClass());
    for (EnterProcessor processor : afterCompletion ? ourAfterCompletionEnterProcessors : 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) && !afterCompletion) {
      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;
    }

    final PsiElement[] children = atCaret.getChildren();
    for (PsiElement child : children) {
      if (atCaret instanceof PsiStatement && child instanceof PsiStatement) continue;
      collectAllElements(child, res, recurse);
    }
  }

  private static boolean doNotStepInto(PsiElement element) {
    return element instanceof PsiClass || element instanceof PsiCodeBlock || element instanceof PsiStatement || element instanceof PsiMethod;
  }

  @Override
  @Nullable
  protected PsiElement getStatementAtCaret(Editor editor, PsiFile psiFile) {
    final PsiElement atCaret = super.getStatementAtCaret(editor, psiFile);

    if (atCaret instanceof PsiWhiteSpace) return null;
    if (atCaret instanceof PsiJavaToken && "}".equals(atCaret.getText()) && !(atCaret.getParent() instanceof PsiArrayInitializerExpression)) return null;

    PsiElement statementAtCaret = PsiTreeUtil.getParentOfType(atCaret,
                                                              PsiStatement.class,
                                                              PsiCodeBlock.class,
                                                              PsiMember.class,
                                                              PsiComment.class,
                                                              PsiImportStatementBase.class
    );

    if (statementAtCaret instanceof PsiBlockStatement) return null;

    if (statementAtCaret != null && statementAtCaret.getParent() instanceof PsiForStatement) {
      if (!PsiTreeUtil.hasErrorElements(statementAtCaret)) {
        statementAtCaret = statementAtCaret.getParent();
      }
    }

    return statementAtCaret instanceof PsiStatement ||
           statementAtCaret instanceof PsiMember ||
           statementAtCaret instanceof PsiImportStatementBase
           ? 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), PsiCodeBlock.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;
    }
  }

  public void setSkipEnter(boolean skipEnter) {
    mySkipEnter = skipEnter;
  }

  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();
  }

}
