/*
 * Copyright 2000-2014 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.
 */

/*
 * Created by IntelliJ IDEA.
 * User: max
 * Date: May 14, 2002
 * Time: 7:18:30 PM
 * To change template for new class use
 * Code Style | Class Templates options (Tools | IDE Options).
 */
package com.intellij.openapi.editor.actions;

import com.intellij.openapi.editor.*;
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.actionSystem.DataContext;
import gnu.trove.TIntHashSet;
import gnu.trove.TIntIntHashMap;
import org.jetbrains.annotations.NotNull;

public class DeleteToWordStartAction extends TextComponentEditorAction {

  /**
   * We need to provide special processing for quote symbols.
   * <p/>
   * Examples:
   *   <table border='1'>
   *     <tr>
   *       <th>Text before action call</td>
   *       <th>Text after action call</td>
   *     </tr>
   *     <tr>
   *       <td>one "two" [caret]</td>
   *       <td>one [caret]</td>
   *     </tr>
   *     <tr>
   *       <td>one "two[caret]"</td>
   *       <td>one "[caret]"</td>
   *     </tr>
   *   </table>
   */
  private static final TIntHashSet QUOTE_SYMBOLS = new TIntHashSet();

  static {
    QUOTE_SYMBOLS.add('\'');
    QUOTE_SYMBOLS.add('\"');
  }

  private static final int[] QUOTE_SYMBOLS_ARRAY = QUOTE_SYMBOLS.toArray();

  public DeleteToWordStartAction() {
    super(new Handler(false));
  }

  static class Handler extends EditorWriteActionHandler {

    @NotNull private final TIntIntHashMap myQuotesNumber = new TIntIntHashMap();
    private final boolean myNegateCamelMode;

    Handler(boolean negateCamelMode) {
      super(true);
      myNegateCamelMode = negateCamelMode;
    }

    @Override
    public void executeWriteAction(Editor editor, DataContext dataContext) {
      CommandProcessor.getInstance().setCurrentCommandGroupId(EditorActionUtil.DELETE_COMMAND_GROUP);
      if (editor.getSelectionModel().hasSelection()) {
        BackspaceAction.doBackspaceAction(editor);
        return;
      }
      deleteToWordStart(editor);
    }

    private void deleteToWordStart(Editor editor) {
      boolean camel = editor.getSettings().isCamelWords();
      if (myNegateCamelMode) {
        camel = !camel;
      }
      CharSequence text = editor.getDocument().getCharsSequence();
      CaretModel caretModel = editor.getCaretModel();
      int endOffset = caretModel.getOffset();
      int minOffset = editor.getDocument().getLineStartOffset(caretModel.getLogicalPosition().line);
      
      myQuotesNumber.clear();
      for (int i : QUOTE_SYMBOLS_ARRAY) {
        myQuotesNumber.put(i, 0);
      }
      countQuotes(myQuotesNumber, text, minOffset, endOffset);
      
      EditorActionUtil.moveCaretToPreviousWord(editor, false, camel);
      
      for (int offset = caretModel.getOffset(); offset > minOffset; offset = caretModel.getOffset()) {
        char previous = text.charAt(offset - 1);
        char current = text.charAt(offset);
        if (QUOTE_SYMBOLS.contains(current)) {
          if (Character.isWhitespace(previous)) {
            break;
          }
          else if (offset < endOffset - 1 && !Character.isJavaIdentifierPart(text.charAt(offset + 1))) {
            // Handle a situation like ' "one", "two", [caret] '. We want to delete up to the previous literal end here.
            editor.getCaretModel().moveToOffset(offset + 1);
            break;
          }
          if (myQuotesNumber.get(current) % 2 == 0) {
            // Was 'one "two" [caret]', now 'one "two[caret]"', we want to get 'one [caret]"two"'
            EditorActionUtil.moveCaretToPreviousWord(editor, false, camel);
            continue;
          }
          break;
        }

        if (QUOTE_SYMBOLS.contains(previous)) {
          if (myQuotesNumber.get(previous) % 2 == 0) {
            // Was 'one "two[caret]", now 'one "[caret]two"', we want 'one [caret]"two"'
            editor.getCaretModel().moveToOffset(offset - 1);
          }
        }
        break;
      }

      int startOffset = caretModel.getOffset();
      Document document = editor.getDocument();
      document.deleteString(startOffset, endOffset);
    }
  }

  private static void countQuotes(@NotNull TIntIntHashMap holder, @NotNull CharSequence text, int start, int end) {
    for (int i = end - 1; i >= start; i--) {
      char c = text.charAt(i);
      if (holder.containsKey(c)) {
        holder.put(c, holder.get(c) + 1);
      }
    }
  }
}
