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

const fs = require('fs');
const http = require('http');
const path = require('path');
const parseURL = require('url').parse;
const {argv} = require('yargs');

const {createInstrumenter} = require('istanbul-lib-instrument');
const convertSourceMap = require('convert-source-map');
const defaultIstanbulSchema = require('@istanbuljs/schema');

const {getTestRunnerConfigSetting} = require('../test/test_config_helpers.js');

const serverPort = parseInt(process.env.PORT, 10) || 8090;
const target = argv.target || process.env.TARGET || 'Default';

/**
 * This configures the base of the URLs that are injected into each component
 * doc example to load. By default it's /, so that we load /front_end/..., but
 * this can be configured if you have a different file structure.
 */
const sharedResourcesBase =
    argv.sharedResourcesBase || getTestRunnerConfigSetting('component-server-shared-resources-path', '/');

/**
 * The server assumes that examples live in
 * devtoolsRoot/out/Target/gen/front_end/ui/components/docs, but if you need to add a
 * prefix you can pass this argument. Passing `foo` will redirect the server to
 * look in devtoolsRoot/out/Target/gen/foo/front_end/ui/components/docs.
 */
const componentDocsBaseArg = argv.componentDocsBase || process.env.COMPONENT_DOCS_BASE ||
    getTestRunnerConfigSetting('component-server-base-path', '');

/**
 * When you run npm run components-server we run the script as is from scripts/,
 * but when this server is run as part of a test suite it's run from
 * out/Default/gen/scripts, so we have to do a bit of path mangling to figure
 * out where we are.
 */
const isRunningInGen = __dirname.includes(path.join('out', path.sep, target));

let pathToOutTargetDir = __dirname;
/**
 * If we are in the gen directory, we need to find the out/Default folder to use
 * as our base to find files from. We could do this with path.join(x, '..',
 * '..') until we get the right folder, but that's brittle. It's better to
 * search up for out/Default to be robust to any folder structures.
 */
while (isRunningInGen && !pathToOutTargetDir.endsWith(`out${path.sep}${target}`)) {
  pathToOutTargetDir = path.resolve(pathToOutTargetDir, '..');
}

/* If we are not running in out/Default, we'll assume the script is running from the repo root, and navigate to {CWD}/out/Target */
const pathToBuiltOutTargetDirectory =
    isRunningInGen ? pathToOutTargetDir : path.resolve(path.join(process.cwd(), 'out', target));

const devtoolsRootFolder = path.resolve(path.join(pathToBuiltOutTargetDirectory, 'gen'));
const componentDocsBaseFolder = path.join(devtoolsRootFolder, componentDocsBaseArg);

if (!fs.existsSync(devtoolsRootFolder)) {
  console.error(`ERROR: Generated front_end folder (${devtoolsRootFolder}) does not exist.`);
  console.log(
      'The components server works from the built Ninja output; you may need to run Ninja to update your built DevTools.');
  console.log('If you build to a target other than default, you need to pass --target=X as an argument');
  process.exit(1);
}

const server = http.createServer(requestHandler);
server.listen(serverPort);
server.once('listening', () => {
  if (process.send) {
    process.send(serverPort);
  }
  console.log(`Started components server at http://localhost:${serverPort}\n`);
  console.log(`ui/components/docs location: ${
      path.relative(process.cwd(), path.join(componentDocsBaseFolder, 'front_end', 'ui', 'components', 'docs'))}`);
});

server.once('error', error => {
  if (process.send) {
    process.send('ERROR');
  }
  throw error;
});

function createComponentIndexFile(componentPath, componentExamples) {
  const componentName = componentPath.replace('/front_end/ui/components/docs/', '').replace(/_/g, ' ').replace('/', '');
  // clang-format off
  return `<!DOCTYPE html>
  <html>
    <head>
      <meta charset="UTF-8" />
      <meta name="viewport" content="width=device-width" />
      <title>DevTools component: ${componentName}</title>
      <style>
        h1 { text-transform: capitalize; }

        .example {
          padding: 5px;
          margin: 10px;
        }

        a:link,
        a:visited {
          color: blue;
          text-decoration: underline;
        }

        a:hover {
          text-decoration: none;
        }
        .example summary {
          font-size: 20px;
        }

        .back-link {
          padding-left: 5px;
          font-size: 16px;
          font-style: italic;
        }

        iframe { display: block; width: 100%; height: 400px; }
      </style>
    </head>
    <body>
      <h1>
        ${componentName}
        <a class="back-link" href="/">Back to index</a>
      </h1>
      ${componentExamples.map(example => {
        const fullPath = path.join(componentPath, example);
        return `<details class="example">
          <summary><a href="${fullPath}">${example.replace('.html', '').replace(/-|_/g, ' ')}</a></summary>
          <iframe src="${fullPath}"></iframe>
        </details>`;
      }).join('\n')}
    </body>
  </html>`;
  // clang-format on
}

function createServerIndexFile(componentNames) {
  // clang-format off
  return `<!DOCTYPE html>
  <html>
    <head>
      <meta charset="UTF-8" />
      <meta name="viewport" content="width=device-width" />
      <title>DevTools components</title>
      <link rel="stylesheet" href="${sharedResourcesBase}front_end/ui/legacy/themeColors.css" />
      <link rel="stylesheet" href="${sharedResourcesBase}front_end/ui/components/docs/component_docs_styles.css" />
    </head>
    <body id="index-page">
      <h1>DevTools components</h1>
      <ul class="components-list">
        ${componentNames.map(name => {
          const niceName = name.replace(/_/g, ' ');
          return `<li><a href='/front_end/ui/components/docs/${name}'>${niceName}</a></li>`;
        }).join('\n')}
      </ul>
    </body>
  </html>`;
  // clang-format on
}

async function getExamplesForPath(filePath) {
  const componentDirectory = path.join(componentDocsBaseFolder, filePath);
  const allFiles = await fs.promises.readdir(componentDirectory);
  const htmlExampleFiles = allFiles.filter(file => {
    return path.extname(file) === '.html';
  });

  return createComponentIndexFile(filePath, htmlExampleFiles);
}

function respondWithHtml(response, html) {
  response.setHeader('Content-Type', 'text/html; charset=utf-8');
  response.writeHead(200);
  response.write(html, 'utf8');
  response.end();
}

function send404(response, message) {
  response.writeHead(404);
  response.write(message, 'utf8');
  response.end();
}

async function checkFileExists(filePath) {
  try {
    const errorsAccessingFile = await fs.promises.access(filePath, fs.constants.R_OK);
    return !errorsAccessingFile;
  } catch (e) {
    return false;
  }
}

const EXCLUDED_COVERAGE_FOLDERS = new Set(['third_party', 'ui/components/docs', 'Images']);

/**
 * @param {string} filePath
 * @returns {boolean}
 */
function isIncludedForCoverageComputation(filePath) {
  for (const excludedFolder of EXCLUDED_COVERAGE_FOLDERS) {
    if (filePath.startsWith(`/front_end/${excludedFolder}/`)) {
      return false;
    }
  }

  return true;
}

const COVERAGE_INSTRUMENTER = createInstrumenter({
  esModules: true,
  parserPlugins: [
    ...defaultIstanbulSchema.instrumenter.properties.parserPlugins.default,
    'topLevelAwait',
  ],
});

const instrumentedSourceCacheForFilePaths = new Map();

const SHOULD_GATHER_COVERAGE_INFORMATION = process.env.COVERAGE === '1';

/**
 * @param {http.IncomingMessage} request
 * @param {http.ServerResponse} response
 */
async function requestHandler(request, response) {
  const filePath = parseURL(request.url).pathname;
  if (filePath === '/favicon.ico') {
    send404(response, '404, no favicon');
    return;
  }

  if (filePath === '/' || filePath === '/index.html') {
    const components =
        await fs.promises.readdir(path.join(componentDocsBaseFolder, 'front_end', 'ui', 'components', 'docs'));
    const html = createServerIndexFile(components.filter(filePath => {
      const stats = fs.lstatSync(path.join(componentDocsBaseFolder, 'front_end', 'ui', 'components', 'docs', filePath));
      // Filter out some build config files (tsconfig, d.ts, etc), and just list the directories.
      return stats.isDirectory();
    }));
    respondWithHtml(response, html);
  } else if (filePath.startsWith('/front_end/ui/components/docs') && path.extname(filePath) === '') {
    // This means it's a component path like /breadcrumbs.
    const componentHtml = await getExamplesForPath(filePath);
    respondWithHtml(response, componentHtml);
    return;
  } else if (/ui\/components\/docs\/(.+)\/(.+)\.html/.test(filePath)) {
    /** This conditional checks if we are viewing an individual example's HTML
     *  file. e.g. localhost:8090/front_end/ui/components/docs/data_grid/basic.html For each
     *  example we inject themeColors.css into the page so all CSS variables
     *  that components use are available.
     */

    /**
    * We also let the user provide a different base path for any shared
    * resources that we load. But if this is provided along with the
    * componentDocsBaseArg, and the two are the same, we don't want to use the
    * shared resources base, as it's part of the componentDocsBaseArg and
    * therefore the URL is already correct.
    *
    * If we didn't get a componentDocsBaseArg or we did and it's different to
    * the sharedResourcesBase, we use sharedResourcesBase.
    */
    const baseUrlForSharedResource =
        componentDocsBaseArg && componentDocsBaseArg.endsWith(sharedResourcesBase) ? '/' : `/${sharedResourcesBase}`;
    const fileContents = await fs.promises.readFile(path.join(componentDocsBaseFolder, filePath), {encoding: 'utf8'});
    const themeColoursLink = `<link rel="stylesheet" href="${
        path.join(baseUrlForSharedResource, 'front_end', 'ui', 'legacy', 'themeColors.css')}" type="text/css" />`;
    const inspectorCommonLink = `<link rel="stylesheet" href="${
        path.join(baseUrlForSharedResource, 'front_end', 'ui', 'legacy', 'inspectorCommon.css')}" type="text/css" />`;
    const toggleDarkModeScript = `<script type="module" src="${
        path.join(baseUrlForSharedResource, 'front_end', 'ui', 'components', 'docs', 'component_docs.js')}"></script>`;
    const newFileContents = fileContents.replace('</head>', `${themeColoursLink}\n${inspectorCommonLink}\n</head>`)
                                .replace('</body>', toggleDarkModeScript + '\n</body>');
    respondWithHtml(response, newFileContents);

  } else {
    // This means it's an asset like a JS file or an image.
    let fullPath = path.join(componentDocsBaseFolder, filePath);
    if (fullPath.endsWith(path.join('locales', 'en-US.json')) &&
        !componentDocsBaseFolder.includes(sharedResourcesBase)) {
      /**
       * If the path is for locales/en-US.json we special case the loading of that to fix the path so it works properly in the server.
       * We also make sure that we take into account the shared resources base;
       * but if the base folder already contains the shared resources base, we don't
       * add it to the path, because otherwise that would cause the shared resources
       * base to be duplicated in the fullPath.
       */
      // Rewrite this path so we can load up the locale in the component-docs
      let prefix = componentDocsBaseFolder;
      if (sharedResourcesBase && !componentDocsBaseFolder.includes(sharedResourcesBase)) {
        prefix = path.join(componentDocsBaseFolder, sharedResourcesBase);
      }
      fullPath = path.join(prefix, 'front_end', 'core', 'i18n', 'locales', 'en-US.json');
    }

    if (!fullPath.startsWith(devtoolsRootFolder) && !fileIsInTestFolder) {
      console.error(`Path ${fullPath} is outside the DevTools Frontend root dir.`);
      process.exit(1);
    }

    const fileExists = await checkFileExists(fullPath);

    if (!fileExists) {
      send404(response, '404, File not found');
      return;
    }

    let encoding = 'utf8';
    if (fullPath.endsWith('.js')) {
      response.setHeader('Content-Type', 'text/javascript; charset=utf-8');
    } else if (fullPath.endsWith('.css')) {
      response.setHeader('Content-Type', 'text/css; charset=utf-8');
    } else if (fullPath.endsWith('.wasm')) {
      response.setHeader('Content-Type', 'application/wasm');
      encoding = 'binary';
    } else if (fullPath.endsWith('.svg')) {
      response.setHeader('Content-Type', 'image/svg+xml; charset=utf-8');
    } else if (fullPath.endsWith('.png')) {
      response.setHeader('Content-Type', 'image/png');
      encoding = 'binary';
    } else if (fullPath.endsWith('.jpg')) {
      response.setHeader('Content-Type', 'image/jpg');
      encoding = 'binary';
    } else if (fullPath.endsWith('.avif')) {
      response.setHeader('Content-Type', 'image/avif');
      encoding = 'binary';
    } else if (fullPath.endsWith('.gz')) {
      response.setHeader('Content-Type', 'application/gzip');
      encoding = 'binary';
    }

    let fileContents = await fs.promises.readFile(fullPath, encoding);
    const isComputingCoverageRequest = request.headers['devtools-compute-coverage'] === '1';

    if (SHOULD_GATHER_COVERAGE_INFORMATION && fullPath.endsWith('.js') && filePath.startsWith('/front_end/') &&
        isIncludedForCoverageComputation(filePath)) {
      const previouslyGeneratedInstrumentedSource = instrumentedSourceCacheForFilePaths.get(fullPath);

      if (previouslyGeneratedInstrumentedSource) {
        fileContents = previouslyGeneratedInstrumentedSource;
      } else {
        if (!isComputingCoverageRequest) {
          response.writeHead(400);
          response.write(`Invalid coverage request. Attempted to load ${request.url}.`, 'utf8');
          response.end();

          console.error(
              `Invalid coverage request. Attempted to load ${request.url} which was not available in the ` +
              'code coverage instrumentation cache. Make sure that you call `preloadForCodeCoverage` in the describe block ' +
              'of your interactions test, before declaring any tests.\n');
          return;
        }

        fileContents = await new Promise(async (resolve, reject) => {
          let sourceMap = convertSourceMap.fromSource(fileContents);
          if (!sourceMap) {
            sourceMap = convertSourceMap.fromMapFileSource(fileContents, path.dirname(fullPath));
          }

          COVERAGE_INSTRUMENTER.instrument(fileContents, fullPath, (error, instrumentedSource) => {
            if (error) {
              reject(error);
            } else {
              resolve(instrumentedSource);
            }
          }, sourceMap ? sourceMap.sourcemap : undefined);
        });

        instrumentedSourceCacheForFilePaths.set(fullPath, fileContents);
      }
    }

    response.writeHead(200);
    response.write(fileContents, encoding);
    response.end();
  }
}
