// 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.

/**
 * Functions in this script parse DevTools frontend .js and module.json files,
 * collect localizable strings, check if frontend strings are in .grd/.grdp
 * files and report error if present.
 */

const fs = require('fs');
const path = require('path');
const {promisify} = require('util');
const writeFileAsync = promisify(fs.writeFile);
const renameFileAsync = promisify(fs.rename);
const localizationUtils = require('./localization_utils');
const escodegen = localizationUtils.escodegen;
const esprimaTypes = localizationUtils.esprimaTypes;
const esprima = localizationUtils.esprima;
const extensionStringKeys = ['category', 'destination', 'title', 'title-mac'];

// Format of frontendStrings
// { IDS_md5-hash => {
//     string: string,
//     code: string,
//     isShared: boolean,
//     filepath: string,
//     grdpPath: string,
//     location: {
//       start: {
//         line: number, (1-based)
//         column: number (0-based)
//       },
//       end: {
//         line: number,
//         column: number
//       }
//     },
//     arguments: string[]
//   }
// }
const frontendStrings = new Map();

// Format
// {
//   IDS_KEY => a list of {
//     actualIDSKey: string,  // the IDS key in the message tag
//     description: string,
//     grdpPath: string,
//     location: {
//       start: {
//         line: number
//       },
//       end: {
//         line: number
//       }
//     }
//   }
// }
const IDSkeys = new Map();
const fileToGRDPMap = new Map();

const devtoolsFrontendPath = path.resolve(__dirname, '..', '..', '..', 'front_end');
let devtoolsFrontendDirs;

/**
 * The following functions validate and update grd/grdp files.
 */

async function validateGrdAndGrdpFiles(shouldAutoFix) {
  const grdError = await validateGrdFile(shouldAutoFix);
  const grdpError = await validateGrdpFiles(shouldAutoFix);
  if (grdError !== '' || grdpError !== '')
    return `${grdError}\n${grdpError}`;
  else
    return '';
}

function expectedGrdpFilePath(dir) {
  return path.resolve(dir, `${path.basename(dir)}_strings.grdp`);
}

async function validateGrdFile(shouldAutoFix) {
  const fileContent = await localizationUtils.parseFileContent(localizationUtils.GRD_PATH);
  const fileLines = fileContent.split('\n');
  const newLines = [];
  let errors = '';
  fileLines.forEach(line => errors += validateGrdLine(line, newLines));
  if (errors !== '' && shouldAutoFix)
    await writeFileAsync(localizationUtils.GRD_PATH, newLines.join('\n'));
  return errors;
}

function validateGrdLine(line, newLines) {
  let error = '';
  const match = line.match(/<part file="([^"]*)" \/>/);
  if (!match) {
    newLines.push(line);
    return error;
  }
  // match[0]: full match
  // match[1]: relative grdp file path
  const grdpFilePath = localizationUtils.getAbsoluteGrdpPath(match[1]);
  const expectedGrdpFile = expectedGrdpFilePath(path.dirname(grdpFilePath));
  if (fs.existsSync(grdpFilePath) &&
      (grdpFilePath === expectedGrdpFile || grdpFilePath === localizationUtils.SHARED_STRINGS_PATH)) {
    newLines.push(line);
    return error;
  } else if (!fs.existsSync(grdpFilePath)) {
    error += `${line.trim()} in ${
                 localizationUtils.getRelativeFilePathFromSrc(
                     localizationUtils.GRD_PATH)} refers to a grdp file that doesn't exist. ` +
        `Please verify the grdp file and update the <part file="..."> entry to reference the correct grdp file. ` +
        `Make sure the grdp file name is ${path.basename(expectedGrdpFile)}.`
  } else {
    error += `${line.trim()} in ${
        localizationUtils.getRelativeFilePathFromSrc(localizationUtils.GRD_PATH)} should reference "${
        localizationUtils.getRelativeGrdpPath(expectedGrdpFile)}".`;
  }
  return error;
}

async function validateGrdpFiles(shouldAutoFix) {
  const frontendDirsToGrdpFiles = await mapFrontendDirsToGrdpFiles();
  const grdFileContent = await localizationUtils.parseFileContent(localizationUtils.GRD_PATH);
  let errors = '';
  const renameFilePromises = [];
  const grdpFilesToAddToGrd = [];
  frontendDirsToGrdpFiles.forEach(
      (grdpFiles, dir) => errors +=
      validateGrdpFile(dir, grdpFiles, grdFileContent, shouldAutoFix, renameFilePromises, grdpFilesToAddToGrd));
  if (grdpFilesToAddToGrd.length > 0)
    await localizationUtils.addChildGRDPFilePathsToGRD(grdpFilesToAddToGrd.sort());
  await Promise.all(renameFilePromises);
  return errors;
}

async function mapFrontendDirsToGrdpFiles() {
  devtoolsFrontendDirs =
      devtoolsFrontendDirs || await localizationUtils.getChildDirectoriesFromDirectory(devtoolsFrontendPath);
  const dirToGrdpFiles = new Map();
  const getGrdpFilePromises = devtoolsFrontendDirs.map(dir => {
    const files = [];
    dirToGrdpFiles.set(dir, files);
    return localizationUtils.getFilesFromDirectory(dir, files, ['.grdp']);
  });
  await Promise.all(getGrdpFilePromises);
  return dirToGrdpFiles;
}

function validateGrdpFile(dir, grdpFiles, grdFileContent, shouldAutoFix, renameFilePromises, grdpFilesToAddToGrd) {
  let error = '';
  const expectedGrdpFile = expectedGrdpFilePath(dir);
  if (grdpFiles.length === 0)
    return error;
  if (grdpFiles.length > 1) {
    throw new Error(`${grdpFiles.length} GRDP files found under ${
        localizationUtils.getRelativeFilePathFromSrc(dir)}. Please make sure there's only one GRDP file named ${
        path.basename(expectedGrdpFile)} under this directory.`);
  }

  // Only one grdp file is under the directory
  if (grdpFiles[0] !== expectedGrdpFile) {
    // Rename grdp file and the reference in the grd file
    if (shouldAutoFix) {
      renameFilePromises.push(renameFileAsync(grdpFiles[0], expectedGrdpFile));
      grdpFilesToAddToGrd.push(expectedGrdpFile);
    } else {
      error += `${localizationUtils.getRelativeFilePathFromSrc(grdpFiles[0])} should be renamed to ${
          localizationUtils.getRelativeFilePathFromSrc(expectedGrdpFile)}.`;
    }
    return error;
  }

  // Only one grdp file and its name follows the naming convention
  if (!grdFileContent.includes(localizationUtils.getRelativeGrdpPath(grdpFiles[0]))) {
    if (shouldAutoFix) {
      grdpFilesToAddToGrd.push(grdpFiles[0]);
    } else {
      error += `Please add ${localizationUtils.createPartFileEntry(grdpFiles[0]).trim()} to ${
          localizationUtils.getRelativeFilePathFromSrc(grdpFiles[0])}.`;
    }
  }
  return error;
}

/**
 * Parse localizable resources.
 */
async function parseLocalizableResourceMaps() {
  if (frontendStrings.size === 0 && IDSkeys.size === 0)
    await parseLocalizableResourceMapsHelper();
  return [frontendStrings, IDSkeys];
}

async function parseLocalizableResourceMapsHelper() {
  const grdpToFiles = new Map();
  const dirs = devtoolsFrontendDirs || await localizationUtils.getChildDirectoriesFromDirectory(devtoolsFrontendPath);
  const grdpToFilesPromises = dirs.map(dir => {
    const files = [];
    grdpToFiles.set(expectedGrdpFilePath(dir), files);
    return localizationUtils.getFilesFromDirectory(dir, files, ['.js', 'module.json']);
  });
  await Promise.all(grdpToFilesPromises);

  const promises = [];
  for (const [grdpPath, files] of grdpToFiles) {
    files.forEach(file => fileToGRDPMap.set(file, grdpPath));
    promises.push(parseLocalizableStrings(files));
  }
  await Promise.all(promises);
  // Parse grd(p) files after frontend strings are processed so we know
  // what to add or remove based on frontend strings
  await parseIDSKeys();
}

/**
 * The following functions parse localizable strings (wrapped in Common.UIString,
 * Common.UIStringFormat, UI.formatLocalized or ls``) from devtools frontend files.
 */

async function parseLocalizableStrings(devtoolsFiles) {
  const promises = devtoolsFiles.map(filePath => parseLocalizableStringsFromFile(filePath));
  await Promise.all(promises);
}

async function parseLocalizableStringsFromFile(filePath) {
  const fileContent = await localizationUtils.parseFileContent(filePath);
  if (path.basename(filePath) === 'module.json')
    return parseLocalizableStringFromModuleJson(fileContent, filePath);

  let ast;
  try {
    ast = esprima.parseModule(fileContent, {loc: true});
  } catch (e) {
    throw new Error(
        `DevTools localization parser failed:\n${localizationUtils.getRelativeFilePathFromSrc(filePath)}: ${
            e.message}` +
        `\nThis error is likely due to unsupported JavaScript features.` +
        ` Such features are not supported by eslint either and will cause presubmit to fail.` +
        ` Please update the code and use official JavaScript features.`);
  }
  for (const node of ast.body) {
    parseLocalizableStringFromNode(node, filePath);
  }
}

function parseLocalizableStringFromModuleJson(fileContent, filePath) {
  const fileJSON = JSON.parse(fileContent);
  if (!fileJSON.extensions)
    return;

  for (const extension of fileJSON.extensions) {
    for (const key in extension) {
      if (extensionStringKeys.includes(key)) {
        addString(extension[key], extension[key], filePath);
      } else if (key === 'device') {
        addString(extension.device.title, extension.device.title, filePath);
      } else if (key === 'options') {
        for (const option of extension.options) {
          addString(option.title, option.title, filePath);
          if (option.text !== undefined)
            addString(option.text, option.text, filePath);
        }
      } else if (key === 'defaultValue' && Array.isArray(extension[key])) {
        for (const defaultVal of extension[key]) {
          if (defaultVal.title)
            addString(defaultVal.title, defaultVal.title, filePath);
        }
      } else if (key === 'tags' && extension[key]) {
        const tagsList = extension[key].split(',');
        for (let tag of tagsList) {
          tag = tag.trim();
          addString(tag, tag, filePath);
        }
      }
    }
  }
}

function parseLocalizableStringFromNode(node, filePath) {
  if (!node)
    return;

  if (Array.isArray(node)) {
    for (const child of node)
      parseLocalizableStringFromNode(child, filePath);

    return;
  }

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

  const locCase = localizationUtils.getLocalizationCase(node);
  switch (locCase) {
    case 'Common.UIString':
    case 'Common.UIStringFormat':
      handleCommonUIString(node, filePath);
      break;
    case 'UI.formatLocalized':
      if (node.arguments !== undefined && node.arguments[1] !== undefined && node.arguments[1].elements !== undefined)
        handleCommonUIString(node, filePath, node.arguments[1].elements);
      break;
    case 'Tagged Template':
      handleTemplateLiteral(node.quasi, escodegen.generate(node), filePath);
      break;
    case null:
      break;
    default:
      throw new Error(
          `${filePath}${localizationUtils.getLocationMessage(node.loc)}: unexpected localization case for node: ${
              escodegen.generate(node)}`);
  }

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

function handleCommonUIString(node, filePath, argumentNodes) {
  if (argumentNodes === undefined)
    argumentNodes = node.arguments.slice(1);
  const firstArgType = node.arguments[0].type;
  switch (firstArgType) {
    case esprimaTypes.LITERAL:
      const message = node.arguments[0].value;
      addString(message, escodegen.generate(node), filePath, node.loc, argumentNodes);
      break;
    case esprimaTypes.TEMP_LITERAL:
      handleTemplateLiteral(node.arguments[0], escodegen.generate(node), filePath, argumentNodes);
      break;
    default:
      break;
  }
}

function handleTemplateLiteral(node, code, filePath, argumentNodes) {
  if (node.expressions.length === 0) {
    // template literal does not contain any variables, parse the value
    addString(node.quasis[0].value.cooked, code, filePath, node.loc, argumentNodes);
    return;
  }

  argumentNodes = node.expressions;
  let processedMsg = '';
  for (let i = 0; i < node.quasis.length; i++) {
    processedMsg += node.quasis[i].value.cooked;
    if (i < node.expressions.length) {
      // add placeholder for variable so that
      // the ph tag gets generated
      processedMsg += '%s';
    }
  }
  addString(processedMsg, code, filePath, node.loc, argumentNodes);
}

function addString(str, code, filePath, location, argumentNodes) {
  const ids = localizationUtils.getIDSKey(str);

  // In the case of duplicates, the corresponding grdp message should be added
  // to the shared strings file only if the duplicate strings span across different
  // grdp files
  const existingString = frontendStrings.get(ids);
  if (existingString) {
    if (!existingString.isShared && existingString.grdpPath !== fileToGRDPMap.get(filePath)) {
      existingString.isShared = true;
      existingString.grdpPath = localizationUtils.SHARED_STRINGS_PATH;
    }
    return;
  }

  const currentString =
      {string: str, code: code, isShared: false, filepath: filePath, grdpPath: fileToGRDPMap.get(filePath)};
  if (location)
    currentString.location = location;
  if (argumentNodes && argumentNodes.length > 0)
    currentString.arguments = argumentNodes.map(argNode => escodegen.generate(argNode));

  frontendStrings.set(ids, currentString);
}

/**
 * The following functions parse <message>s and their IDS keys from
 * devtools frontend grdp files.
 */

async function parseIDSKeys() {
  // NOTE: this function assumes that no <message> tags are present in the parent
  const grdpFilePaths = await parseGRDFile();
  await parseGRDPFiles(grdpFilePaths);
}

async function parseGRDFile() {
  const fileContent = await localizationUtils.parseFileContent(localizationUtils.GRD_PATH);
  const grdFileDir = path.dirname(localizationUtils.GRD_PATH);
  const partFileRegex = /<part file="(.*?)"/g;

  let match;
  const grdpFilePaths = new Set();
  while ((match = partFileRegex.exec(fileContent)) !== null) {
    if (match.index === partFileRegex.lastIndex)
      partFileRegex.lastIndex++;
    // match[0]: full match
    // match[1]: part file path
    grdpFilePaths.add(path.resolve(grdFileDir, match[1]));
  }
  return grdpFilePaths;
}

function parseGRDPFiles(grdpFilePaths) {
  const promises = Array.from(grdpFilePaths, grdpFilePath => parseGRDPFile(grdpFilePath));
  return Promise.all(promises);
}

function trimGrdpPlaceholder(placeholder) {
  const exampleRegex = new RegExp('<ex>.*?<\/ex>', 'gms');
  // $1s<ex>my example</ex> -> $1s
  return placeholder.replace(exampleRegex, '').trim();
}

function convertToFrontendPlaceholders(message) {
  // <ph name="phname">$1s<ex>my example</ex></ph> and <ph name="phname2">$2.3f</ph>
  // match[0]: <ph name="phname1">$1s</ph>
  // match[1]: $1s<ex>my example</ex>
  let placeholderRegex = new RegExp('<ph[^>]*>(.*?)<\/ph>', 'gms');
  let match;
  while ((match = placeholderRegex.exec(message)) !== null) {
    const placeholder = match[0];
    const placeholderValue = trimGrdpPlaceholder(match[1]);
    const newPlaceholderValue = placeholderValue.replace(/\$[1-9]/, '%');
    message =
        message.substring(0, match.index) + newPlaceholderValue + message.substring(match.index + placeholder.length);
    // Modified the message, so search from the beginning of the string again.
    placeholderRegex.lastIndex = 0;
  }
  return message;
}

async function parseGRDPFile(filePath) {
  const fileContent = await localizationUtils.parseFileContent(filePath);

  function stripWhitespacePadding(message) {
    let match = message.match(/^'''/);
    if (match)
      message = message.substring(3);
    match = message.match(/(.*?)'''$/);
    if (match)
      message = match[1];
    return message;
  }

  // Example:
  //  <message name="IDS_DEVTOOLS_md5_hash" desc="Description of this message">
  //      Message text here with optional placeholders <ph name="phname">$1s</ph>
  //  </message>
  // match[0]: the entire '<message>...</message>' block.
  // match[1]: 'IDS_DEVTOOLS_md5_hash'
  // match[2]: 'Description of this message'
  // match[3]: '     Message text here with optional placeholders <ph name="phname">$1s</ph>\n  '
  const messageRegex = new RegExp('<message[^>]*name="([^"]*)"[^>]*desc="([^"]*)"[^>]*>\s*\r?\n(.*?)<\/message>', 'gms');
  let match;
  while ((match = messageRegex.exec(fileContent)) !== null) {
    const line = localizationUtils.lineNumberOfIndex(fileContent, match.index);
    const actualIDSKey = match[1];
    const description = match[2];
    let message = match[3];
    message = convertToFrontendPlaceholders(message.trim());
    message = stripWhitespacePadding(message);
    message = localizationUtils.sanitizeStringIntoFrontendFormat(message);

    const ids = localizationUtils.getIDSKey(message);
    addMessage(ids, actualIDSKey, filePath, line, description);
  }
}

function addMessage(expectedIDSKey, actualIDSKey, grdpPath, line, description) {
  if (!IDSkeys.has(expectedIDSKey))
    IDSkeys.set(expectedIDSKey, []);

  IDSkeys.get(expectedIDSKey).push({actualIDSKey, grdpPath, location: {start: {line}, end: {line}}, description});
}

/**
 * The following functions compare frontend localizable strings
 * with grdp <message>s and report error of resources to add,
 * remove or modify.
 */
function getAndReportResourcesToAdd() {
  const keysToAddToGRD = getMessagesToAdd();
  if (keysToAddToGRD.size === 0)
    return;

  let errorStr = 'The following frontend string(s) need to be added to GRD/GRDP file(s).\n';
  errorStr += 'Please refer to auto-generated message(s) below and modify as needed.\n\n';

  // Example error message:
  // third_party/devtools-frontend/front_end/network/NetworkDataGridNode.js Line 973: ls`(disk cache)`
  // Add a new message tag for this string to third_party\devtools-frontend\front_end\network\network_strings.grdp
  // <message name="IDS_DEVTOOLS_ad86890fb40822a3b12627efaca4ecd7" desc="Fill in the description.">
  //   (disk cache)
  // </message>
  for (const [key, stringObj] of keysToAddToGRD) {
    errorStr += `${localizationUtils.getRelativeFilePathFromSrc(stringObj.filepath)}${
        localizationUtils.getLocationMessage(stringObj.location)}: ${stringObj.code}\n`;
    errorStr += `Add a new message tag for this string to ${
        localizationUtils.getRelativeFilePathFromSrc(fileToGRDPMap.get(stringObj.filepath))}\n\n`;
    errorStr += localizationUtils.createGrdpMessage(key, stringObj);
  }
  return errorStr;
}

function getAndReportResourcesToRemove() {
  const keysToRemoveFromGRD = getMessagesToRemove();
  if (keysToRemoveFromGRD.size === 0)
    return;

  let errorStr =
      '\nThe message(s) associated with the following IDS key(s) should be removed from its GRD/GRDP file(s):\n';
  // Example error message:
  // third_party/devtools-frontend/front_end/accessibility/accessibility_strings.grdp Line 300: IDS_DEVTOOLS_c9bbad3047af039c14d0e7ec957bb867
  for (const [ids, messages] of keysToRemoveFromGRD) {
    messages.forEach(
        message => errorStr += `${localizationUtils.getRelativeFilePathFromSrc(message.grdpPath)}${
            localizationUtils.getLocationMessage(message.location)}: ${ids}\n\n`);
  }
  return errorStr;
}

function getAndReportIDSKeysToModify() {
  const messagesToModify = getIDSKeysToModify();
  if (messagesToModify.size === 0)
    return;

  let errorStr = '\nThe following GRD/GRDP message(s) do not have the correct IDS key.\n';
  errorStr += 'Please update the key(s) by changing the "name" value.\n\n';

  for (const [expectedIDSKey, messages] of messagesToModify) {
    messages.forEach(
        message => errorStr += `${localizationUtils.getRelativeFilePathFromSrc(message.grdpPath)}${
            localizationUtils.getLocationMessage(
                message.location)}:\n${message.actualIDSKey} --> ${expectedIDSKey}\n\n`);
  }
  return errorStr;
}

function getMessagesToAdd() {
  // If a message with ids key exists in grdpPath
  function messageExists(ids, grdpPath) {
    const messages = IDSkeys.get(ids);
    return messages.some(message => message.grdpPath === grdpPath);
  }

  const difference = [];
  for (const [ids, frontendString] of frontendStrings) {
    if (!IDSkeys.has(ids) || !messageExists(ids, frontendString.grdpPath))
      difference.push([ids, frontendString]);
  }
  return new Map(difference.sort());
}

// Return a map from the expected IDS key to a list of messages
// whose actual IDS keys need to be modified.
function getIDSKeysToModify() {
  const messagesToModify = new Map();
  for (const [expectedIDSKey, messages] of IDSkeys) {
    for (const message of messages) {
      if (expectedIDSKey !== message.actualIDSKey) {
        if (messagesToModify.has(expectedIDSKey))
          messagesToModify.get(expectedIDSKey).push(message);
        else
          messagesToModify.set(expectedIDSKey, [message]);
      }
    }
  }
  return messagesToModify;
}

function getMessagesToRemove() {
  const difference = new Map();
  for (const [ids, messages] of IDSkeys) {
    if (!frontendStrings.has(ids)) {
      difference.set(ids, messages);
      continue;
    }

    const expectedGrdpPath = frontendStrings.get(ids).grdpPath;
    const messagesInGrdp = [];
    const messagesToRemove = [];
    messages.forEach(message => {
      if (message.grdpPath !== expectedGrdpPath)
        messagesToRemove.push(message);
      else
        messagesInGrdp.push(message);
    });

    if (messagesToRemove.length === 0 && messagesInGrdp.length === 1)
      continue;

    if (messagesInGrdp.length > 1) {
      // If there are more than one messages with ids in the
      // expected grdp file, keep one with the longest
      // description and delete all the other messages
      const longestDescription = getLongestDescription(messagesInGrdp);
      let foundMessageToKeep = false;
      for (const message of messagesInGrdp) {
        if (message.description === longestDescription && !foundMessageToKeep) {
          foundMessageToKeep = true;
          continue;
        }
        messagesToRemove.push(message);
      }
    }
    difference.set(ids, messagesToRemove);
  }
  return difference;
}

function getLongestDescription(messages) {
  let longestDescription = '';
  messages.forEach(message => {
    if (message.description.length > longestDescription.length)
      longestDescription = message.description;
  });
  return longestDescription;
}

module.exports = {
  parseLocalizableResourceMaps,
  getAndReportIDSKeysToModify,
  getAndReportResourcesToAdd,
  getAndReportResourcesToRemove,
  getIDSKeysToModify,
  getLongestDescription,
  getMessagesToAdd,
  getMessagesToRemove,
  validateGrdAndGrdpFiles,
};
