// Copyright 2019 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
'use strict';

// Description: Scans for localizability violations in the DevTools front-end.
// Checks all .grdp files and reports messages without descriptions and placeholder examples.
// Audits all Common.UIString(), UI.formatLocalized(), and ls`` calls and
// checks for misuses of concatenation and conditionals. It also looks for
// specific arguments to functions that are expected to be a localized string.
// Since the check scans for common error patterns, it might misidentify something.
// In this case, add it to the excluded errors at the top of the script.

const path = require('path');
const localizationUtils = require('./utils/localization_utils');
const esprimaTypes = localizationUtils.esprimaTypes;
const escodegen = localizationUtils.escodegen;
const esprima = localizationUtils.esprima;

// Exclude known errors
const excludeErrors = [
  'Common.UIString(view.title())', 'Common.UIString(setting.title() || \'\')', 'Common.UIString(option.text)',
  'Common.UIString(experiment.title)', 'Common.UIString(phase.message)',
  'Common.UIString(Help.latestReleaseNote().header)', 'Common.UIString(conditions.title)',
  'Common.UIString(extension.title())', 'Common.UIString(this._currentValueLabel, value)'
];

const usage = `Usage: node ${path.basename(process.argv[0])} [-a | <.js file path>*]

-a: If present, check all devtools frontend .js files
<.js file path>*: List of .js files with absolute paths separated by a space
`;

async function main() {
  if (process.argv.length < 3 || process.argv[2] === '--help') {
    console.log(usage);
    process.exit(0);
  }

  const errors = [];

  try {
    let filePaths = [];
    const frontendPath = path.resolve(__dirname, '..', '..', 'front_end');
    let filePathPromises = [localizationUtils.getFilesFromDirectory(frontendPath, filePaths, ['.grdp'])];
    if (process.argv[2] === '-a') {
      filePathPromises.push(localizationUtils.getFilesFromDirectory(frontendPath, filePaths, ['.js']));
    } else {
      // esprima has a bug parsing a valid JSON format, so exclude them.
      filePaths = process.argv.slice(2).filter( file => {
        return (path.extname(file) !== '.json') && localizationUtils.shouldParseDirectory(file);
      });
    }
    await Promise.all(filePathPromises);

    filePaths.push(localizationUtils.SHARED_STRINGS_PATH);
    const auditFilePromises = filePaths.map(filePath => auditFileForLocalizability(filePath, errors));
    await Promise.all(auditFilePromises);
  } catch (err) {
    console.log(err);
    process.exit(1);
  }

  if (errors.length > 0) {
    console.log(`DevTools localization checker detected errors!\n${errors.join('\n')}`);
    process.exit(1);
  }
  console.log('DevTools localization checker passed');
}

main();

function includesConditionalExpression(listOfElements) {
  return listOfElements.filter(ele => ele !== undefined && ele.type === esprimaTypes.COND_EXPR).length > 0;
}

function addError(error, errors) {
  if (!errors.includes(error))
    errors.push(error);
}

function buildConcatenatedNodesList(node, nodes) {
  if (!node)
    return;
  if (node.left === undefined && node.right === undefined) {
    nodes.push(node);
    return;
  }
  buildConcatenatedNodesList(node.left, nodes);
  buildConcatenatedNodesList(node.right, nodes);
}

/**
 * Recursively check if there is concatenation to localization call.
 * Concatenation is allowed between localized strings and strings that
 * don't contain letters.
 * Example (allowed): ls`Status code: ${statusCode}`
 * Example (allowed): ls`Status code` + ': '
 * Example (disallowed): ls`Status code: ` + statusCode
 * Example (disallowed): ls`Status ` + 'code'
 */
function checkConcatenation(parentNode, node, filePath, errors) {
  function isConcatenationDisallowed(node) {
    if (node.type !== esprimaTypes.LITERAL && node.type !== esprimaTypes.TEMP_LITERAL)
      return true;

    let value;
    if (node.type === esprimaTypes.LITERAL)
      value = node.value;
    else if (node.type === esprimaTypes.TEMP_LITERAL && node.expressions.length === 0)
      value = node.quasis[0].value.cooked;

    if (!value || typeof value !== 'string')
      return true;

    return value.match(/[a-z]/i) !== null;
  }

  function isConcatenation(node) {
    return (node !== undefined && node.type === esprimaTypes.BI_EXPR && node.operator === '+');
  }

  if (isConcatenation(parentNode))
    return;

  if (isConcatenation(node)) {
    const concatenatedNodes = [];
    buildConcatenatedNodesList(node, concatenatedNodes);
    const nonLocalizationCalls = concatenatedNodes.filter(node => !localizationUtils.isLocalizationCall(node));
    const hasLocalizationCall = nonLocalizationCalls.length !== concatenatedNodes.length;
    if (hasLocalizationCall) {
      // concatenation with localization call
      const hasConcatenationViolation = nonLocalizationCalls.some(isConcatenationDisallowed);
      if (hasConcatenationViolation) {
        const code = escodegen.generate(node);
        addError(
            `${localizationUtils.getRelativeFilePathFromSrc(filePath)}${
                localizationUtils.getLocationMessage(
                    node.loc)}: string concatenation should be changed to variable substitution with ls: ${code}`,
            errors);
      }
    }
  }
}

/**
 * Check if an argument of a function is localized.
 */
function checkFunctionArgument(functionName, argumentIndex, node, filePath, errors) {
  if (node !== undefined && node.type === esprimaTypes.CALL_EXPR &&
      localizationUtils.verifyFunctionCallee(node.callee, functionName) && node.arguments !== undefined &&
      node.arguments.length > argumentIndex) {
    const arg = node.arguments[argumentIndex];
    // No need to localize empty strings.
    if (arg.type === esprimaTypes.LITERAL && arg.value === '')
      return;

    if (!localizationUtils.isLocalizationCall(arg)) {
      let order = '';
      switch (argumentIndex) {
        case 0:
          order = 'first';
          break;
        case 1:
          order = 'second';
          break;
        case 2:
          order = 'third';
          break;
        default:
          order = `${argumentIndex + 1}th`;
      }
      addError(
          `${localizationUtils.getRelativeFilePathFromSrc(filePath)}${
              localizationUtils.getLocationMessage(
                  node.loc)}: ${order} argument to ${functionName}() should be localized: ${escodegen.generate(node)}`,
          errors);
    }
  }
}

/**
 * Check esprima node object that represents the AST of code
 * to see if there is any localization error.
 */
function analyzeNode(parentNode, node, filePath, errors) {
  if (node === undefined || node === null)
    return;

  if (node instanceof Array) {
    for (const child of node)
      analyzeNode(node, child, filePath, errors);

    return;
  }

  const keys = Object.keys(node);
  const objKeys = keys.filter(key => {
    return typeof node[key] === 'object' && key !== 'loc';
  });
  if (objKeys.length === 0) {
    // base case: all values are non-objects -> node is a leaf
    return;
  }

  const locCase = localizationUtils.getLocalizationCase(node);
  const code = escodegen.generate(node);
  switch (locCase) {
    case 'Common.UIString':
    case 'UI.formatLocalized':
      const firstArgType = node.arguments[0].type;
      if (firstArgType !== esprimaTypes.LITERAL && firstArgType !== esprimaTypes.TEMP_LITERAL &&
          firstArgType !== esprimaTypes.IDENTIFIER && !excludeErrors.includes(code)) {
        addError(
            `${localizationUtils.getRelativeFilePathFromSrc(filePath)}${
                localizationUtils.getLocationMessage(node.loc)}: first argument to call should be a string: ${code}`,
            errors);
      }
      if (includesConditionalExpression(node.arguments.slice(1))) {
        addError(
            `${localizationUtils.getRelativeFilePathFromSrc(filePath)}${
                localizationUtils.getLocationMessage(node.loc)}: conditional(s) found in ${
                code}. Please extract conditional(s) out of the localization call.`,
            errors);
      }
      break;
    case 'Tagged Template':
      if (includesConditionalExpression(node.quasi.expressions)) {
        addError(
            `${localizationUtils.getRelativeFilePathFromSrc(filePath)}${
                localizationUtils.getLocationMessage(node.loc)}: conditional(s) found in ${
                code}. Please extract conditional(s) out of the localization call.`,
            errors);
      }
      break;
    default:
      // String concatenation to localization call(s) should be changed
      checkConcatenation(parentNode, node, filePath, errors);
      break;
  }

  for (const key of objKeys) {
    // recursively parse all the child nodes
    analyzeNode(node, node[key], filePath, errors);
  }
}

function auditGrdpFile(filePath, fileContent, errors) {
  function reportMissingPlaceholderExample(messageContent, lineNumber) {
    const phRegex = /<ph[^>]*name="([^"]*)">\$\d(s|d|\.\df)(?!<ex>)<\/ph>/gms;
    let match;
    // ph tag that contains $1.2f format placeholder without <ex>
    // match[0]: full match
    // match[1]: ph name
    while ((match = phRegex.exec(messageContent)) !== null) {
      addError(
          `${localizationUtils.getRelativeFilePathFromSrc(filePath)} Line ${
              lineNumber +
              localizationUtils.lineNumberOfIndex(
                  messageContent, match.index)}: missing <ex> in <ph> tag with the name "${match[1]}"`,
          errors);
    }
  }

  function reportMissingDescriptionAndPlaceholderExample() {
    const messageRegex = /<message[^>]*name="([^"]*)"[^>]*desc="([^"]*)"[^>]*>\s*\n(.*?)<\/message>/gms;
    let match;
    // match[0]: full match
    // match[1]: message IDS_ key
    // match[2]: description
    // match[3]: message content
    while ((match = messageRegex.exec(fileContent)) !== null) {
      const lineNumber = localizationUtils.lineNumberOfIndex(fileContent, match.index);
      if (match[2].trim() === '') {
        addError(
            `${localizationUtils.getRelativeFilePathFromSrc(filePath)} Line ${
                lineNumber}: missing description for message with the name "${match[1]}"`,
            errors);
      }
      reportMissingPlaceholderExample(match[3], lineNumber);
    }
  }

  reportMissingDescriptionAndPlaceholderExample();
}

async function auditFileForLocalizability(filePath, errors) {
  const fileContent = await localizationUtils.parseFileContent(filePath);
  if (path.extname(filePath) === '.grdp')
    return auditGrdpFile(filePath, fileContent, errors);

  const ast = esprima.parseModule(fileContent, {loc: true});

  const relativeFilePath = localizationUtils.getRelativeFilePathFromSrc(filePath);
  for (const node of ast.body)
    analyzeNode(undefined, node, relativeFilePath, errors);
}
