/*
 * Copyright 2000-2013 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.siyeh.ipp.unicode;

import com.intellij.openapi.editor.CaretModel;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.siyeh.ipp.base.Intention;
import com.siyeh.ipp.base.PsiElementEditorPredicate;
import com.siyeh.ipp.base.PsiElementPredicate;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

/**
 * @author Bas Leijdekkers
 */
public class UnicodeUnescapeIntention extends Intention {

  @Override
  protected void processIntention(@NotNull PsiElement element) {}

  @Override
  protected void processIntention(Editor editor, @NotNull PsiElement element) {
    final SelectionModel selectionModel = editor.getSelectionModel();
    if (selectionModel.hasSelection()) {
      // does not check if octal escape is inside char or string literal (garbage in, garbage out)
      final Document document = editor.getDocument();
      final int start = selectionModel.getSelectionStart();
      final int end = selectionModel.getSelectionEnd();
      final String text = document.getText(new TextRange(start, end));
      final int textLength = end - start;
      final StringBuilder replacement = new StringBuilder(textLength);
      int anchor = 0;
      while (true) {
        final int index = indexOfUnicodeEscape(text, anchor + 1);
        if (index < 0) {
          break;
        }
        replacement.append(text.substring(anchor, index));
        int hexStart = index + 1;
        while (text.charAt(hexStart) == 'u') {
          hexStart++;
        }
        anchor = hexStart + 4;
        final int c = Integer.parseInt(text.substring(hexStart, anchor), 16);
        replacement.appendCodePoint(c);
      }
      replacement.append(text.substring(anchor, textLength));
      document.replaceString(start, end, replacement);
    }
    else {
      final CaretModel caretModel = editor.getCaretModel();
      final Document document = editor.getDocument();
      final int lineNumber = document.getLineNumber(caretModel.getOffset());
      final int lineStartOffset = document.getLineStartOffset(lineNumber);
      final String line = document.getText(new TextRange(lineStartOffset, document.getLineEndOffset(lineNumber)));
      final int column = caretModel.getLogicalPosition().column;
      final int index1 = indexOfUnicodeEscape(line, column);
      final int index2 = indexOfUnicodeEscape(line, column + 1);
      final int escapeStart = index2 == column ? index2 : index1; // if caret is between two unicode escape, replace the right one
      int hexStart = escapeStart + 1;
      while (line.charAt(hexStart) == 'u') {
        hexStart++;
      }
      final int c = Integer.parseInt(line.substring(hexStart, hexStart + 4), 16);
      document.replaceString(lineStartOffset + escapeStart, lineStartOffset + hexStart + 4, String.valueOf((char) c));
    }
  }

  /**
   * see JLS 3.3. Unicode Escapes
   */
  private static int indexOfUnicodeEscape(@NotNull String text, int offset) {
    final int length = text.length();
    for (int i = 0; i < length; i++) {
      final char c = text.charAt(i);
      if (c != '\\') {
        continue;
      }
      boolean isEscape = true;
      int previousChar = i - 1;
      while (previousChar >= 0 && text.charAt(previousChar) == '\\') {
        isEscape = !isEscape;
        previousChar--;
      }
      if (!isEscape) {
        continue;
      }
      int nextChar = i;
      do {
        nextChar++;
        if (nextChar >= length) {
          break;
        }
      }
      while (text.charAt(nextChar) == 'u'); // \uuuu0061 is a legal unicode escape
      if (nextChar == i + 1 || nextChar + 3 >= length) {
        break;
      }
      if (StringUtil.isHexDigit(text.charAt(nextChar)) &&
          StringUtil.isHexDigit(text.charAt(nextChar + 1)) &&
          StringUtil.isHexDigit(text.charAt(nextChar + 2)) &&
          StringUtil.isHexDigit(text.charAt(nextChar + 3))) {
        final int escapeEnd = nextChar + 4;
        if (offset <= escapeEnd) {
          return i;
        }
      }
    }
    return -1;
  }

  @NotNull
  @Override
  protected PsiElementPredicate getElementPredicate() {
    return new UnicodeEscapePredicate();
  }

  private static class UnicodeEscapePredicate extends PsiElementEditorPredicate {
    @Override
    public boolean satisfiedBy(PsiElement element, @Nullable Editor editor) {
      if (editor == null) {
        return false;
      }
      final SelectionModel selectionModel = editor.getSelectionModel();
      final Document document = editor.getDocument();
      if (selectionModel.hasSelection()) {
        final int start = selectionModel.getSelectionStart();
        final int end = selectionModel.getSelectionEnd();
        if (start < 0 || end < 0 || start > end) {
          // shouldn't happen but http://ea.jetbrains.com/browser/ea_problems/50192
          return false;
        }
        final String text = document.getCharsSequence().subSequence(start, end).toString();
        return indexOfUnicodeEscape(text, 1) >= 0;
      }
      else {
        final CaretModel caretModel = editor.getCaretModel();
        final int lineNumber = document.getLineNumber(caretModel.getOffset());
        final String line = document.getText(new TextRange(document.getLineStartOffset(lineNumber), document.getLineEndOffset(lineNumber)));
        final int column = caretModel.getLogicalPosition().column;
        final int index = indexOfUnicodeEscape(line, column);
        return index >= 0 && column >= index;
      }
    }
  }
}
