/**
 * @fileoverview This is a collection of smaller utility functions to operate on
 * a TypeScript AST, used by JSConformance rules and elsewhere.
 */

import * as ts from 'typescript';

/**
 * Triggers increased verbosity in the rules.
 */
let DEBUG = false;

/**
 * Turns on or off logging for ConformancePatternRules.
 */
export function setDebug(state: boolean) {
  DEBUG = state;
}

/**
 * Debug helper.
 */
export function debugLog(msg: string) {
  if (DEBUG) console.log(msg);
}

/**
 * Returns `n`'s parents in order.
 */
export function parents(n: ts.Node): ts.Node[] {
  const p = [];
  while (n.parent) {
    n = n.parent;
    p.push(n);
  }
  return p;
}

/**
 * Searches for something satisfying the given test in `n` or its children.
 */
export function findInChildren(
    n: ts.Node, test: (n: ts.Node) => boolean): boolean {
  let toExplore: ts.Node[] = [n];
  let cur: ts.Node|undefined;
  while (cur = toExplore.pop()) {
    if (test(cur)) {
      return true;
    }
    // Recurse
    toExplore = toExplore.concat(cur.getChildren());
  }
  return false;
}

/**
 * Returns true if the pattern-based Rule should look at that node and consider
 * warning there. The goal is to make it easy to exclude on source files,
 * blocks, module declarations, JSDoc, lib.d.ts nodes, that kind of things.
 */
export function shouldExamineNode(n: ts.Node) {
  return !(
      ts.isBlock(n) || ts.isModuleBlock(n) || ts.isModuleDeclaration(n) ||
      ts.isSourceFile(n) || (n.parent && ts.isTypeNode(n.parent)) ||
      ts.isJSDoc(n) || isInStockLibraries(n));
}

/**
 * Return whether the given declaration is ambient.
 */
export function isAmbientDeclaration(d: ts.Declaration): boolean {
  return Boolean(
      d.modifiers &&
      d.modifiers.some(m => m.kind === ts.SyntaxKind.DeclareKeyword));
}

/**
 * Return whether the given Node is (or is in) a library included as default.
 * We currently look for a node_modules/typescript/ prefix, but this could
 * be expanded if needed.
 */
export function isInStockLibraries(n: ts.Node|ts.SourceFile): boolean {
  const sourceFile = ts.isSourceFile(n) ? n : n.getSourceFile();
  if (sourceFile) {
    return sourceFile.fileName.indexOf('node_modules/typescript/') !== -1;
  } else {
    // the node is nowhere? Consider it as part of the core libs: we can't do
    // anything with it anyways, and it was likely included as default.
    return true;
  }
}

/**
 * Turns the given Symbol into its non-aliased version (which could be itself).
 * Returns undefined if given an undefined Symbol (so you can call
 * `dealias(typeChecker.getSymbolAtLocation(node))`).
 */
export function dealias(
    symbol: ts.Symbol|undefined, tc: ts.TypeChecker): ts.Symbol|undefined {
  if (!symbol) {
    return undefined;
  }
  if (symbol.getFlags() & ts.SymbolFlags.Alias) {
    // Note: something that has only TypeAlias is not acceptable here.
    return dealias(tc.getAliasedSymbol(symbol), tc);
  }
  return symbol;
}

/**
 * Returns whether `n`'s parents are something indicating a type.
 */
export function isPartOfTypeDeclaration(n: ts.Node) {
  return [n, ...parents(n)].some(
      p => p.kind === ts.SyntaxKind.TypeReference ||
          p.kind === ts.SyntaxKind.TypeLiteral);
}

/**
 * Returns whether `n` is under an import statement.
 */
export function isPartOfImportStatement(n: ts.Node) {
  return [n, ...parents(n)].some(
      p => p.kind === ts.SyntaxKind.ImportDeclaration);
}

/**
 * Returns whether `n` is a declaration.
 */
export function isDeclaration(n: ts.Node): n is ts.VariableDeclaration|
    ts.ClassDeclaration|ts.FunctionDeclaration|ts.MethodDeclaration|
    ts.PropertyDeclaration|ts.VariableDeclarationList|ts.InterfaceDeclaration|
    ts.TypeAliasDeclaration|ts.EnumDeclaration|ts.ModuleDeclaration|
    ts.ImportDeclaration|ts.ImportEqualsDeclaration|ts.ExportDeclaration|
    ts.MissingDeclaration {
  return ts.isVariableDeclaration(n) || ts.isClassDeclaration(n) ||
      ts.isFunctionDeclaration(n) || ts.isMethodDeclaration(n) ||
      ts.isPropertyDeclaration(n) || ts.isVariableDeclarationList(n) ||
      ts.isInterfaceDeclaration(n) || ts.isTypeAliasDeclaration(n) ||
      ts.isEnumDeclaration(n) || ts.isModuleDeclaration(n) ||
      ts.isImportDeclaration(n) || ts.isImportEqualsDeclaration(n) ||
      ts.isExportDeclaration(n) || ts.isMissingDeclaration(n);
}

/** Type guard for expressions that looks like property writes. */
export function isPropertyWriteExpression(node: ts.Node):
    node is(ts.BinaryExpression & {
      left: ts.PropertyAccessExpression;
    }) {
  if (!ts.isBinaryExpression(node)) {
    return false;
  }
  if (node.operatorToken.getText().trim() !== '=') {
    return false;
  }
  if (!ts.isPropertyAccessExpression(node.left) ||
      node.left.expression.getFullText().trim() === '') {
    return false;
  }

  // TODO: Destructuring assigments aren't covered. This would be a potential
  // bypass, but I doubt we'd catch bugs, so fixing it seems low priority
  // overall.

  return true;
}

/**
 * If verbose, logs the given error that happened while walking n, with a
 * stacktrace.
 */
export function logASTWalkError(verbose: boolean, n: ts.Node, e: Error) {
  let nodeText = `[error getting name for ${JSON.stringify(n)}]`;
  try {
    nodeText = '"' + n.getFullText().trim() + '"';
  } catch {
  }
  debugLog(
      `Walking node ${nodeText} failed with error ${e}.\n` +
      `Stacktrace:\n${e.stack}`);
}
