/*
 * Copyright 2016 The Bazel Authors. All rights reserved.
 *
 * 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.google.idea.blaze.base.lang.buildfile.editor;

import com.google.idea.blaze.base.lang.buildfile.lexer.BuildToken;
import com.google.idea.blaze.base.lang.buildfile.psi.*;
import com.google.idea.blaze.base.lang.buildfile.psi.util.PsiUtils;
import com.intellij.codeInsight.editorActions.enter.EnterHandlerDelegateAdapter;
import com.intellij.ide.DataManager;
import com.intellij.injected.editor.EditorWindow;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.editor.actionSystem.EditorActionHandler;
import com.intellij.openapi.editor.actions.SplitLineAction;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.codeStyle.CodeStyleSettings;
import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
import com.intellij.psi.codeStyle.CommonCodeStyleSettings.IndentOptions;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.util.text.CharArrayUtil;

import javax.annotation.Nullable;

/**
 * Inserts indents as appropriate when enter is pressed.<br>
 * This is a substitute for implementing a full FormattingModel for the BUILD language.
 * If we ever decide to do that, this code should be removed.
 */
public class BuildEnterHandler extends EnterHandlerDelegateAdapter {

  @Override
  public Result preprocessEnter(PsiFile file,
                                Editor editor,
                                Ref<Integer> caretOffset,
                                Ref<Integer> caretAdvance,
                                DataContext dataContext,
                                EditorActionHandler originalHandler) {
    int offset = caretOffset.get();
    if (editor instanceof EditorWindow) {
      file = InjectedLanguageManager.getInstance(file.getProject()).getTopLevelFile(file);
      editor = InjectedLanguageUtil.getTopLevelEditor(editor);
      offset = editor.getCaretModel().getOffset();
    }
    if (!isApplicable(file, dataContext)) {
      return Result.Continue;
    }

    // Previous enter handler's (e.g. EnterBetweenBracesHandler) can introduce a mismatch
    // between the editor's caret model and the offset we've been provided with.
    editor.getCaretModel().moveToOffset(offset);

    Document doc = editor.getDocument();
    PsiDocumentManager.getInstance(file.getProject()).commitDocument(doc);

    CodeStyleSettings currentSettings = CodeStyleSettingsManager.getSettings(file.getProject());
    IndentOptions indentOptions = currentSettings.getIndentOptions(file.getFileType());

    Integer indent = determineIndent(file, editor, offset, indentOptions);
    if (indent == null) {
      return Result.Continue;
    }

    removeTrailingWhitespace(doc, file, offset);
    originalHandler.execute(editor, editor.getCaretModel().getCurrentCaret(), dataContext);
    LogicalPosition position = editor.getCaretModel().getLogicalPosition();
    if (position.column == indent) {
      return Result.Stop;
    }
    if (position.column > indent) {
      //default enter handler has added too many spaces -- remove them
      int excess = position.column - indent;
      doc.deleteString(editor.getCaretModel().getOffset() - excess, editor.getCaretModel().getOffset());
    } else if (position.column < indent) {
      String spaces = StringUtil.repeatSymbol(' ', indent - position.column);
      doc.insertString(editor.getCaretModel().getOffset(), spaces);
    }
    editor.getCaretModel().moveToLogicalPosition(new LogicalPosition(position.line, indent));
    return Result.Stop;
  }

  private static void removeTrailingWhitespace(Document doc, PsiFile file, int offset) {
    CharSequence chars = doc.getCharsSequence();
    int start = offset;
    while (offset < chars.length() && chars.charAt(offset) == ' ') {
      PsiElement element = file.findElementAt(offset);
      if (element == null || !(element instanceof PsiWhiteSpace)) {
        break;
      }
      offset++;
    }
    if (start != offset) {
      doc.deleteString(start, offset);
    }
  }

  private static boolean isApplicable(PsiFile file, DataContext dataContext) {
    if (!(file instanceof BuildFile)) {
      return false;
    }
    Boolean isSplitLine = DataManager.getInstance().loadFromDataContext(dataContext, SplitLineAction.SPLIT_LINE_KEY);
    if (isSplitLine != null) {
      return false;
    }
    return true;
  }

  /**
   * Returns null if an appropriate indent cannot be found. In that case we do nothing,
   * and pass it along to the next EnterHandler.
   */
  @Nullable
  private static Integer determineIndent(PsiFile file, Editor editor, int offset, IndentOptions indentOptions) {
    if (offset == 0) {
      return null;
    }
    Document doc = editor.getDocument();
    PsiElement element = getRelevantElement(file, doc, offset);
    PsiElement parent = element != null ? element.getParent() : null;
    if (parent == null) {
      return null;
    }
    if (endsBlock(element)) {
      // current line indent subtract block indent
      return Math.max(0, getIndent(doc, element) - indentOptions.INDENT_SIZE);
    }

    if (parent instanceof BuildListType) {
      BuildListType list = (BuildListType) parent;
      int listOffset = list.getStartOffset();
      LogicalPosition caretPosition = editor.getCaretModel().getLogicalPosition();
      LogicalPosition listStart = editor.offsetToLogicalPosition(listOffset);
      if (listStart.line != caretPosition.line) {
        // take the minimum of the current line's indent and the current caret position
        return indentOfLineUpToCaret(doc, caretPosition.line, offset);
      }
      BuildElement firstChild = ((BuildListType) parent).getFirstElement();
      if (firstChild != null && firstChild.getNode().getStartOffset() < offset) {
        return getIndent(doc, firstChild);
      }
      return lineIndent(doc, listStart.line) + additionalIndent(parent, indentOptions);
    }
    if (parent instanceof StatementListContainer && afterColon(doc, offset)) {
      return getIndent(doc, parent) + additionalIndent(parent, indentOptions);
    }
    return null;
  }

  private static int additionalIndent(PsiElement parent, IndentOptions indentOptions) {
    return parent instanceof StatementListContainer
      ? indentOptions.INDENT_SIZE : indentOptions.CONTINUATION_INDENT_SIZE;
  }

  private static int lineIndent(Document doc, int line) {
    int startOffset = doc.getLineStartOffset(line);
    int indentOffset = CharArrayUtil.shiftForward(doc.getCharsSequence(), startOffset, " \t");
    return indentOffset - startOffset;
  }

  private static int getIndent(Document doc, PsiElement element) {
    int offset = element.getNode().getStartOffset();
    int lineNumber = doc.getLineNumber(offset);
    return offset - doc.getLineStartOffset(lineNumber);
  }

  private static int indentOfLineUpToCaret(Document doc, int line, int caretOffset) {
    int startOffset = doc.getLineStartOffset(line);
    int indentOffset = CharArrayUtil.shiftForward(doc.getCharsSequence(), startOffset, " \t");
    return Math.min(indentOffset, caretOffset) - startOffset;
  }

  private static boolean endsBlock(PsiElement element) {
    return element instanceof ReturnStatement
      || element instanceof PassStatement;
  }

  private static PsiElement getBlockEndingParent(PsiElement element) {
    while (element != null && !(element instanceof PsiFileSystemItem)) {
      if (endsBlock(element)) {
        return element;
      }
      element = element.getParent();
    }
    return null;
  }

  @Nullable
  private static PsiElement getRelevantElement(PsiFile file, Document doc, int offset) {
    if (offset == 0) {
      return null;
    }
    if (offset == doc.getTextLength()) {
      offset--;
    }
    PsiElement element = file.findElementAt(offset);
    while (element != null && isWhiteSpace(element)) {
      element = PsiUtils.getPreviousNodeInTree(element);
    }
    PsiElement blockTerminator = getBlockEndingParent(element);
    if (blockTerminator != null
        && blockTerminator.getTextRange().getEndOffset() == element.getTextRange().getEndOffset()) {
      return blockTerminator;
    }
    while (element != null && skipElement(element, offset)) {
      element = element.getParent();
    }
    return element;
  }

  private static boolean isWhiteSpace(PsiElement element) {
    if (element instanceof PsiWhiteSpace) {
      return true;
    }
    return BuildToken.WHITESPACE_AND_NEWLINE.contains(element.getNode().getElementType());
  }

  private static boolean skipElement(PsiElement element, int offset) {
    PsiElement parent = element.getParent();
    if (parent == null || parent.getNode() == null || parent instanceof PsiFileSystemItem) {
      return false;
    }
    TextRange childRange = element.getNode().getTextRange();
    return childRange.equals(parent.getNode().getTextRange())
      || childRange.getStartOffset() == offset && (parent instanceof Argument || parent instanceof Parameter);
  }

  private static boolean afterColon(Document doc, int offset) {
    CharSequence text = doc.getCharsSequence();
    int previousOffset = CharArrayUtil.shiftBackward(text, offset - 1, " \t");
    return text.charAt(previousOffset) == ':';
  }

}
