/**
 * @fileoverview Bans using a promise as a condition. Promises are always
 * truthy, and this pattern is likely to be a bug where the developer meant
 * if(await returnsPromise()) {} and forgot the await.
 */

import * as tsutils from 'tsutils';
import * as ts from 'typescript';

import {Checker} from '../checker';
import {ErrorCode} from '../error_code';
import {AbstractRule} from '../rule';

export class Rule extends AbstractRule {
  readonly ruleName = 'ban-promise-as-condition';
  readonly code = ErrorCode.BAN_PROMISE_AS_CONDITION;

  register(checker: Checker) {
    checker.on(
        ts.SyntaxKind.ConditionalExpression, checkConditional, this.code);
    checker.on(
        ts.SyntaxKind.BinaryExpression, checkBinaryExpression, this.code);
    checker.on(ts.SyntaxKind.WhileStatement, checkWhileStatement, this.code);
    checker.on(ts.SyntaxKind.IfStatement, checkIfStatement, this.code);
  }
}

/** Error message to display. */
function thenableText(nodeType: string, isVariable: boolean) {
  return `Found a thenable ${isVariable ? 'variable' : 'return value'} being` +
      ` used as ${
             nodeType}. Promises are always truthy, await the value to get` +
      ' a boolean value.';
}

function thenableVariableText(nodeType: string) {
  return thenableText(nodeType, true);
}

function thenableReturnText(nodeType: string) {
  return thenableText(nodeType, false);
}

/** Ternary: prom ? y : z */
function checkConditional(checker: Checker, node: ts.ConditionalExpression) {
  addFailureIfThenableCallExpression(
      checker, node.condition, thenableReturnText('a conditional'));

  addFailureIfThenableIdentifier(
      checker, node.condition, thenableVariableText('a conditional'));
}

/**
 *  Binary expression: prom || y or prom && y. Only check left side because
 *  myThing && myThing.prom seems legitimate.
 */
function checkBinaryExpression(checker: Checker, node: ts.BinaryExpression) {
  if (node.operatorToken.kind !== ts.SyntaxKind.BarBarToken &&
      node.operatorToken.kind !== ts.SyntaxKind.AmpersandAmpersandToken) {
    return;
  }

  addFailureIfThenableCallExpression(
      checker, node.left, thenableReturnText('a binary expression'));

  addFailureIfThenableIdentifier(
      checker, node.left, thenableVariableText('a binary expression'));
}

/** While statement: while (prom) {} */
function checkWhileStatement(checker: Checker, node: ts.WhileStatement) {
  addFailureIfThenableCallExpression(
      checker, node.expression, thenableReturnText('a while statement'));

  addFailureIfThenableIdentifier(
      checker, node.expression, thenableVariableText('a while  statement'));
}

/** If statement: if (prom) {} */
function checkIfStatement(checker: Checker, node: ts.IfStatement) {
  addFailureIfThenableCallExpression(
      checker, node.expression, thenableReturnText('an if statement'));

  addFailureIfThenableIdentifier(
      checker, node.expression, thenableVariableText('an if statement'));
}

/** Helper methods */

function addFailureIfThenableCallExpression(
    checker: Checker, callExpression: ts.Expression, errorMessage: string) {
  if (!tsutils.isCallExpression(callExpression)) {
    return;
  }

  const typeChecker = checker.typeChecker;
  const signature = typeChecker.getResolvedSignature(callExpression);

  // Return value of getResolvedSignature is `Signature | undefined` in ts 3.1
  // so we must check if the return value is valid to compile with ts 3.1.
  if (!signature) {
    throw new Error('Unexpected undefined signature for call expression');
  }

  const returnType = typeChecker.getReturnTypeOfSignature(signature);

  if (isNonFalsyThenableType(typeChecker, callExpression, returnType)) {
    checker.addFailureAtNode(callExpression, errorMessage);
  }
}

function addFailureIfThenableIdentifier(
    checker: Checker, identifier: ts.Expression, errorMessage: string) {
  if (!tsutils.isIdentifier(identifier)) {
    return;
  }

  if (isNonFalsyThenableType(checker.typeChecker, identifier)) {
    checker.addFailureAtNode(identifier, errorMessage);
  }
}

/**
 * If the type is a union type and has a falsy part it may be legitimate to use
 * it as a condition, so allow those through. (e.g. Promise<boolean> | boolean)
 * Otherwise, check if it's thenable. If so it should be awaited.
 */
function isNonFalsyThenableType(
    typeChecker: ts.TypeChecker, node: ts.Expression,
    type = typeChecker.getTypeAtLocation(node)) {
  if (hasFalsyParts(typeChecker.getTypeAtLocation(node))) {
    return false;
  }

  return tsutils.isThenableType(typeChecker, node, type);
}

function hasFalsyParts(type: ts.Type) {
  const typeParts = tsutils.unionTypeParts(type);
  const hasFalsyParts =
      typeParts.filter((part) => tsutils.isFalsyType(part)).length > 0;
  return hasFalsyParts;
}
