/*
 * 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.
 */
package com.intellij.psi.impl;

import com.intellij.lang.ASTNode;
import com.intellij.lang.LighterASTNode;
import com.intellij.lang.LighterASTTokenNode;
import com.intellij.lang.impl.PsiBuilderImpl;
import com.intellij.openapi.application.Application;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.UserDataHolderBase;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.SourceTreeToPsiMap;
import com.intellij.psi.impl.source.tree.CompositeElement;
import com.intellij.psi.impl.source.tree.SharedImplUtil;
import com.intellij.psi.impl.source.tree.TreeElement;
import com.intellij.psi.stubs.ObjectStubSerializer;
import com.intellij.psi.stubs.Stub;
import com.intellij.psi.tree.IElementType;
import com.intellij.util.*;
import com.intellij.util.diff.FlyweightCapableTreeStructure;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.IOException;
import java.util.List;

@SuppressWarnings({"HardCodedStringLiteral", "UtilityClassWithoutPrivateConstructor", "UnusedDeclaration", "TestOnlyProblems"})
public class DebugUtil {
  private static final Logger LOG = Logger.getInstance("#com.intellij.psi.impl.DebugUtil");

  public static class LengthBuilder implements Appendable {
    private int myLength = 0;

    public int getLength() {
      return myLength;
    }

    @Override
    public Appendable append(final CharSequence csq) {
      myLength += csq.length();
      return this;
    }

    @Override
    public Appendable append(final CharSequence csq, final int start, final int end) {
      myLength += csq.subSequence(start, end).length();
      return this;
    }

    @Override
    public Appendable append(final char c) {
      myLength++;
      return this;
    }
  }

  public static /*final*/ boolean CHECK = false;
  public static final boolean DO_EXPENSIVE_CHECKS;
  static {
    Application application = ApplicationManager.getApplication();
    DO_EXPENSIVE_CHECKS = application != null && application.isUnitTestMode();
  }
  public static final boolean CHECK_INSIDE_ATOMIC_ACTION_ENABLED = DO_EXPENSIVE_CHECKS;

  public static String psiTreeToString(@NotNull final PsiElement element, final boolean skipWhitespaces) {
    final ASTNode node = SourceTreeToPsiMap.psiElementToTree(element);
    assert node != null : element;
    return treeToString(node, skipWhitespaces);
  }

  public static String treeToString(@NotNull final ASTNode root, final boolean skipWhitespaces) {
    final LengthBuilder ruler = new LengthBuilder();
    treeToBuffer(ruler, root, 0, skipWhitespaces, false, false, true);
    final StringBuilder buffer = new StringBuilder(ruler.getLength());
    treeToBuffer(buffer, root, 0, skipWhitespaces, false, false, true);
    return buffer.toString();
  }

  public static String nodeTreeToString(@NotNull final ASTNode root, final boolean skipWhitespaces) {
    final LengthBuilder ruler = new LengthBuilder();
    treeToBuffer(ruler, root, 0, skipWhitespaces, false, false, false);
    final StringBuilder buffer = new StringBuilder(ruler.getLength());
    treeToBuffer(buffer, root, 0, skipWhitespaces, false, false, false);
    return buffer.toString();
  }

  public static String treeToString(@NotNull ASTNode root, boolean skipWhitespaces, boolean showRanges) {
    final LengthBuilder ruler = new LengthBuilder();
    treeToBuffer(ruler, root, 0, skipWhitespaces, showRanges, false, true);
    final StringBuilder buffer = new StringBuilder(ruler.getLength());
    treeToBuffer(buffer, root, 0, skipWhitespaces, showRanges, false, true);
    return buffer.toString();
  }

  public static String treeToStringWithUserData(TreeElement root, boolean skipWhitespaces) {
    final LengthBuilder ruler = new LengthBuilder();
    treeToBufferWithUserData(ruler, root, 0, skipWhitespaces);
    final StringBuilder buffer = new StringBuilder(ruler.getLength());
    treeToBufferWithUserData(buffer, root, 0, skipWhitespaces);
    return buffer.toString();
  }

  public static String treeToStringWithUserData(PsiElement root, boolean skipWhitespaces) {
    final LengthBuilder ruler = new LengthBuilder();
    treeToBufferWithUserData(ruler, root, 0, skipWhitespaces);
    final StringBuilder buffer = new StringBuilder(ruler.getLength());
    treeToBufferWithUserData(buffer, root, 0, skipWhitespaces);
    return buffer.toString();
  }

  public static void treeToBuffer(@NotNull final Appendable buffer,
                                  @NotNull final ASTNode root,
                                  final int indent,
                                  final boolean skipWhiteSpaces,
                                  final boolean showRanges,
                                  final boolean showChildrenRanges,
                                  final boolean usePsi) {
    treeToBuffer(buffer, root, indent, skipWhiteSpaces, showRanges, showChildrenRanges, usePsi, null);
  }

  public static void treeToBuffer(@NotNull final Appendable buffer,
                                  @NotNull final ASTNode root,
                                  final int indent,
                                  final boolean skipWhiteSpaces,
                                  final boolean showRanges,
                                  final boolean showChildrenRanges,
                                  final boolean usePsi,
                                  PairConsumer<PsiElement, Consumer<PsiElement>> extra) {
    if (skipWhiteSpaces && root.getElementType() == TokenType.WHITE_SPACE) return;

    StringUtil.repeatSymbol(buffer, ' ', indent);
    try {
      PsiElement psiElement = null;
      if (root instanceof CompositeElement) {
        if (usePsi) {
          psiElement = root.getPsi();
          if (psiElement != null) {
            buffer.append(psiElement.toString());
          }
          else {
            buffer.append(root.getElementType().toString());
          }
        }
        else {
          buffer.append(root.toString());
        }
      }
      else {
        final String text = fixWhiteSpaces(root.getText());
        buffer.append(root.toString()).append("('").append(text).append("')");
      }
      if (showRanges) buffer.append(root.getTextRange().toString());
      buffer.append("\n");
      if (root instanceof CompositeElement) {
        ASTNode child = root.getFirstChildNode();

        if (child == null) {
          StringUtil.repeatSymbol(buffer, ' ', indent + 2);
          buffer.append("<empty list>\n");
        }
        else {
          while (child != null) {
            treeToBuffer(buffer, child, indent + 2, skipWhiteSpaces, showChildrenRanges, showChildrenRanges, usePsi, extra);
            child = child.getTreeNext();
          }
        }
      }
      if (psiElement != null && extra != null ) {
        extra.consume(psiElement, new Consumer<PsiElement>() {
          @Override
          public void consume(PsiElement element) {
            treeToBuffer(buffer, element.getNode(), indent + 2, skipWhiteSpaces, showChildrenRanges, showChildrenRanges, usePsi, null);
          }
        });
      }
    }
    catch (IOException e) {
      LOG.error(e);
    }
  }

  public static String lightTreeToString(@NotNull final FlyweightCapableTreeStructure<LighterASTNode> tree,
                                         final boolean skipWhitespaces) {
    final LengthBuilder ruler = new LengthBuilder();
    lightTreeToBuffer(tree, tree.getRoot(), ruler, 0, skipWhitespaces);
    final StringBuilder buffer = new StringBuilder(ruler.getLength());
    lightTreeToBuffer(tree, tree.getRoot(), buffer, 0, skipWhitespaces);
    return buffer.toString();
  }

  public static void lightTreeToBuffer(@NotNull final FlyweightCapableTreeStructure<LighterASTNode> tree,
                                       @NotNull final LighterASTNode node,
                                       @NotNull final Appendable buffer,
                                       final int indent,
                                       final boolean skipWhiteSpaces) {
    final IElementType tokenType = node.getTokenType();
    if (skipWhiteSpaces && tokenType == TokenType.WHITE_SPACE) return;

    final boolean isLeaf = (node instanceof LighterASTTokenNode);

    StringUtil.repeatSymbol(buffer, ' ', indent);
    try {
      if (tokenType == TokenType.ERROR_ELEMENT) {
        buffer.append("PsiErrorElement:").append(PsiBuilderImpl.getErrorMessage(node));
      }
      else if (tokenType == TokenType.WHITE_SPACE) {
        buffer.append("PsiWhiteSpace");
      }
      else {
        buffer.append(isLeaf ? "PsiElement" : "Element").append('(').append(tokenType.toString()).append(')');
      }

      if (isLeaf) {
        final String text = ((LighterASTTokenNode)node).getText().toString();
        buffer.append("('").append(fixWhiteSpaces(text)).append("')");
      }
      buffer.append('\n');

      if (!isLeaf) {
        final Ref<LighterASTNode[]> kids = new Ref<LighterASTNode[]>();
        final int numKids = tree.getChildren(tree.prepareForGetChildren(node), kids);
        if (numKids == 0) {
          StringUtil.repeatSymbol(buffer, ' ', indent + 2);
          buffer.append("<empty list>\n");
        }
        else {
          for (int i = 0; i < numKids; i++) {
            lightTreeToBuffer(tree, kids.get()[i], buffer, indent + 2, skipWhiteSpaces);
          }
        }
      }
    }
    catch (IOException e) {
      LOG.error(e);
    }
  }

  public static String stubTreeToString(final Stub root) {
    final LengthBuilder ruler = new LengthBuilder();
    stubTreeToBuffer(root, ruler, 0);
    final StringBuilder builder = new StringBuilder(ruler.getLength());
    stubTreeToBuffer(root, builder, 0);
    return builder.toString();
  }

  public static void stubTreeToBuffer(final Stub node, final Appendable buffer, final int indent) {
    StringUtil.repeatSymbol(buffer, ' ', indent);
    try {
      final ObjectStubSerializer stubType = node.getStubType();
      if (stubType != null) {
        buffer.append(stubType.toString()).append(':');
      }
      buffer.append(node.toString()).append('\n');

      @SuppressWarnings({"unchecked"})
      final List<? extends Stub> children = node.getChildrenStubs();
      for (final Stub child : children) {
        stubTreeToBuffer(child, buffer, indent + 2);
      }
    }
    catch (IOException e) {
      LOG.error(e);
    }
  }

  private static void treeToBufferWithUserData(Appendable buffer, TreeElement root, int indent, boolean skipWhiteSpaces) {
    if (skipWhiteSpaces && root.getElementType() == TokenType.WHITE_SPACE) return;

    StringUtil.repeatSymbol(buffer, ' ', indent);
    try {
      final PsiElement psi = SourceTreeToPsiMap.treeElementToPsi(root);
      assert psi != null : root;
      if (root instanceof CompositeElement) {
        buffer.append(psi.toString());
      }
      else {
        final String text = fixWhiteSpaces(root.getText());
        buffer.append(root.toString()).append("('").append(text).append("')");
      }
      buffer.append(root.getUserDataString());
      buffer.append("\n");
      if (root instanceof CompositeElement) {
        PsiElement[] children = psi.getChildren();

        for (PsiElement child : children) {
          treeToBufferWithUserData(buffer, (TreeElement)SourceTreeToPsiMap.psiElementToTree(child), indent + 2, skipWhiteSpaces);
        }

        if (children.length == 0) {
          StringUtil.repeatSymbol(buffer, ' ', indent + 2);
          buffer.append("<empty list>\n");
        }
      }
    }
    catch (IOException e) {
      LOG.error(e);
    }
  }

  private static void treeToBufferWithUserData(Appendable buffer, PsiElement root, int indent, boolean skipWhiteSpaces) {
    if (skipWhiteSpaces && root instanceof PsiWhiteSpace) return;

    StringUtil.repeatSymbol(buffer, ' ', indent);
    try {
      if (root instanceof CompositeElement) {
        buffer.append(root.toString());
      }
      else {
        final String text = fixWhiteSpaces(root.getText());
        buffer.append(root.toString()).append("('").append(text).append("')");
      }
      buffer.append(((UserDataHolderBase)root).getUserDataString());
      buffer.append("\n");

      PsiElement[] children = root.getChildren();

      for (PsiElement child : children) {
        treeToBufferWithUserData(buffer, child, indent + 2, skipWhiteSpaces);
      }

      if (children.length == 0) {
        StringUtil.repeatSymbol(buffer, ' ', indent + 2);
        buffer.append("<empty list>\n");
      }
    }
    catch (IOException e) {
      LOG.error(e);
    }
  }

  public static void doCheckTreeStructure(@Nullable ASTNode anyElement) {
    if (anyElement == null) return;
    ASTNode root = anyElement;
    while (root.getTreeParent() != null) {
      root = root.getTreeParent();
    }
    if (root instanceof CompositeElement) {
      checkSubtree((CompositeElement)root);
    }
  }

  private static void checkSubtree(CompositeElement root) {
    if (root.rawFirstChild() == null) {
      if (root.rawLastChild() != null) {
        throw new IncorrectTreeStructureException(root, "firstChild == null, but lastChild != null");
      }
    }
    else {
      for (ASTNode child = root.getFirstChildNode(); child != null; child = child.getTreeNext()) {
        if (child instanceof CompositeElement) {
          checkSubtree((CompositeElement)child);
        }
        if (child.getTreeParent() != root) {
          throw new IncorrectTreeStructureException(child, "child has wrong parent value");
        }
        if (child == root.getFirstChildNode()) {
          if (child.getTreePrev() != null) {
            throw new IncorrectTreeStructureException(root, "firstChild.prev != null");
          }
        }
        else {
          if (child.getTreePrev() == null) {
            throw new IncorrectTreeStructureException(child, "not first child has prev == null");
          }
          if (child.getTreePrev().getTreeNext() != child) {
            throw new IncorrectTreeStructureException(child, "element.prev.next != element");
          }
        }
        if (child.getTreeNext() == null) {
          if (root.getLastChildNode() != child) {
            throw new IncorrectTreeStructureException(child, "not last child has next == null");
          }
        }
      }
    }
  }

  public static void checkParentChildConsistent(@NotNull ASTNode element) {
    ASTNode treeParent = element.getTreeParent();
    if (treeParent == null) return;
    ASTNode[] elements = treeParent.getChildren(null);
    if (ArrayUtil.find(elements, element) == -1) {
      throw new IncorrectTreeStructureException(element, "child cannot be found among parents children");
    }
    //LOG.debug("checked consistence: "+System.identityHashCode(element));
  }

  public static void checkSameCharTabs(@NotNull ASTNode element1, @NotNull ASTNode element2) {
    final CharTable fromCharTab = SharedImplUtil.findCharTableByTree(element1);
    final CharTable toCharTab = SharedImplUtil.findCharTableByTree(element2);
    LOG.assertTrue(fromCharTab == toCharTab);
  }

  public static String psiToString(@NotNull PsiElement element, final boolean skipWhitespaces) {
    return psiToString(element, skipWhitespaces, false);
  }

  public static String psiToString(@NotNull final PsiElement root, final boolean skipWhiteSpaces, final boolean showRanges) {
    return psiToString(root, skipWhiteSpaces, showRanges, null);
  }

  public static String psiToString(@NotNull final PsiElement root, final boolean skipWhiteSpaces, final boolean showRanges, PairConsumer<PsiElement, Consumer<PsiElement>> extra) {
    final LengthBuilder ruler = new LengthBuilder();
    psiToBuffer(ruler, root, skipWhiteSpaces, showRanges, extra);
    final StringBuilder buffer = new StringBuilder(ruler.getLength());
    psiToBuffer(buffer, root, skipWhiteSpaces, showRanges, extra);
    return buffer.toString();
  }

  private static void psiToBuffer(final Appendable buffer,
                                  final PsiElement root,
                                  final boolean skipWhiteSpaces,
                                  final boolean showRanges,
                                  PairConsumer<PsiElement, Consumer<PsiElement>> extra) {
    final ASTNode node = root.getNode();
    if (node == null) {
      psiToBuffer(buffer, root, 0, skipWhiteSpaces, showRanges, showRanges, extra);
    }
    else {
      treeToBuffer(buffer, node, 0, skipWhiteSpaces, showRanges, showRanges, true, extra);
    }
  }

  public static void psiToBuffer(@NotNull final Appendable buffer,
                                 @NotNull final PsiElement root,
                                 int indent,
                                 boolean skipWhiteSpaces,
                                 boolean showRanges,
                                 boolean showChildrenRanges) {
    psiToBuffer(buffer, root, indent, skipWhiteSpaces, showRanges, showChildrenRanges, null);
  }

  public static void psiToBuffer(@NotNull final Appendable buffer,
                                 @NotNull final PsiElement root,
                                 final int indent,
                                 final boolean skipWhiteSpaces,
                                 boolean showRanges,
                                 final boolean showChildrenRanges,
                                 PairConsumer<PsiElement, Consumer<PsiElement>> extra) {
    if (skipWhiteSpaces && root instanceof PsiWhiteSpace) return;

    StringUtil.repeatSymbol(buffer, ' ', indent);
    try {
      buffer.append(root.toString());
      PsiElement child = root.getFirstChild();
      if (child == null) {
        final String text = root.getText();
        assert text != null : "text is null for <" + root + ">";
        buffer.append("('").append(fixWhiteSpaces(text)).append("')");
      }

      if (showRanges) buffer.append(root.getTextRange().toString());
      buffer.append("\n");
      while (child != null) {
        psiToBuffer(buffer, child, indent + 2, skipWhiteSpaces, showChildrenRanges, showChildrenRanges, extra);
        child = child.getNextSibling();
      }
      if (extra != null) {
        extra.consume(root, new Consumer<PsiElement>() {
          @Override
          public void consume(PsiElement element) {
            psiToBuffer(buffer, element, indent + 2, skipWhiteSpaces, showChildrenRanges, showChildrenRanges, null);
          }
        });
      }
    }
    catch (IOException e) {
      LOG.error(e);
    }
  }

  public static String fixWhiteSpaces(String text) {
    text = StringUtil.replace(text, "\n", "\\n");
    text = StringUtil.replace(text, "\r", "\\r");
    text = StringUtil.replace(text, "\t", "\\t");
    return text;
  }

  public static String currentStackTrace() {
    return ExceptionUtil.getThrowableText(new Throwable());
  }

  public static class IncorrectTreeStructureException extends RuntimeException {
    private final ASTNode myElement;

    public IncorrectTreeStructureException(ASTNode element, String message) {
      super(message);
      myElement = element;
    }

    public ASTNode getElement() {
      return myElement;
    }
  }

  private static final ThreadLocal<Object> ourPsiModificationTrace = new ThreadLocal<Object>();
  private static final ThreadLocal<Integer> ourPsiModificationDepth = new ThreadLocal<Integer>();

  /**
   * Marks a start of PSI modification action. Any PSI/AST elements invalidated inside such an action will contain a debug trace
   * identifying this transaction, and so will {@link com.intellij.psi.PsiInvalidElementAccessException} thrown when accessing such invalid 
   * elements. This should help finding out why a specific PSI element has become invalid.
   * 
   * @param trace The debug trace that the invalidated elements should be identified by. May be null, then current stack trace is used.
   */
  public static void startPsiModification(@Nullable String trace) {
    if (!PsiInvalidElementAccessException.isTrackingInvalidation()) {
      return;
    }

    //noinspection ThrowableResultOfMethodCallIgnored
    if (ourPsiModificationTrace.get() == null) {
      ourPsiModificationTrace.set(trace != null ? trace : new Throwable());
    }
    Integer depth = ourPsiModificationDepth.get();
    if (depth == null) depth = 0;
    ourPsiModificationDepth.set(depth + 1);
  }

  /**
   * Finished PSI modification action.
   * @see #startPsiModification(String) 
   */
  public static void finishPsiModification() {
    if (!PsiInvalidElementAccessException.isTrackingInvalidation()) {
      return;
    }
    Integer depth = ourPsiModificationDepth.get();
    if (depth == null) {
      LOG.warn("Unmatched PSI modification end", new Throwable());
      depth = 0;
    } else {
      depth--;
      ourPsiModificationDepth.set(depth);
    }
    if (depth == 0) {
      ourPsiModificationTrace.set(null);
    }
  }

  public static void onInvalidated(@NotNull ASTNode treeElement) {
    Object trace = calcInvalidationTrace(treeElement);
    if (trace != null) {
      PsiInvalidElementAccessException.setInvalidationTrace(treeElement, trace);
    }
  }

  public static void onInvalidated(@NotNull FileViewProvider provider) {
    Object trace = calcInvalidationTrace(null);
    if (trace != null) {
      PsiInvalidElementAccessException.setInvalidationTrace(provider, trace);
    }
  }

  @Nullable
  private static Object calcInvalidationTrace(@Nullable ASTNode treeElement) {
    if (!PsiInvalidElementAccessException.isTrackingInvalidation()) {
      return null;
    }
    if (PsiInvalidElementAccessException.findInvalidationTrace(treeElement) != null) {
      return null;
    }

    Object trace = ourPsiModificationTrace.get();
    if (trace == null) {
      trace = new Throwable();
      LOG.info("PSI invalidated outside transaction", (Throwable)trace);
    }
    return trace;
  }

  public static void revalidateNode(@NotNull ASTNode element) {
    PsiInvalidElementAccessException.setInvalidationTrace(element, null);
  }

  public static void sleep(long millis) {
    TimeoutUtil.sleep(millis);
  }
  public static void checkTreeStructure(ASTNode element) {
    if (CHECK){
      doCheckTreeStructure(element);
    }
  }

}
