'use strict';

const toposort = require('toposort');
const _ = require('lodash');

/**
  Sorts dependencies between chunks by their "parents" attribute.

  This function sorts chunks based on their dependencies with each other.
  The parent relation between chunks as generated by Webpack for each chunk
  is used to define a directed (and hopefully acyclic) graph, which is then
  topologically sorted in order to retrieve the correct order in which
  chunks need to be embedded into HTML. A directed edge in this graph is
  describing a "is parent of" relationship from a chunk to another (distinct)
  chunk. Thus topological sorting orders chunks from bottom-layer chunks to
  highest level chunks that use the lower-level chunks.

  @param {Array} chunks an array of chunks as generated by the html-webpack-plugin.
  - For webpack < 4, It is assumed that each entry contains at least the properties
  "id" (containing the chunk id) and "parents" (array containing the ids of the
  parent chunks).
  - For webpack 4+ the see the chunkGroups param for parent-child relationships

  @param {Array} chunks an array of ChunkGroups that has a getParents method.
  Each ChunkGroup contains a list of chunks in order.

  @return {Array} A topologically sorted version of the input chunks
*/
module.exports.dependency = (chunks, options, compilation) => {
  const chunkGroups = compilation.chunkGroups;
  if (!chunks) {
    return chunks;
  }

  // We build a map (chunk-id -> chunk) for faster access during graph building.
  const nodeMap = {};

  chunks.forEach(chunk => {
    nodeMap[chunk.id] = chunk;
  });

  // Next, we add an edge for each parent relationship into the graph
  let edges = [];

  if (chunkGroups) {
    // Add an edge for each parent (parent -> child)
    edges = chunkGroups.reduce((result, chunkGroup) => result.concat(
      Array.from(chunkGroup.parentsIterable, parentGroup => [parentGroup, chunkGroup])
    ), []);
    const sortedGroups = toposort.array(chunkGroups, edges);
    // flatten chunkGroup into chunks
    const sortedChunks = sortedGroups
      .reduce((result, chunkGroup) => result.concat(chunkGroup.chunks), [])
      .map(chunk => // use the chunk from the list passed in, since it may be a filtered list
    nodeMap[chunk.id])
      .filter((chunk, index, self) => {
        // make sure exists (ie excluded chunks not in nodeMap)
        const exists = !!chunk;
        // make sure we have a unique list
        const unique = self.indexOf(chunk) === index;
        return exists && unique;
      });
    return sortedChunks;
  } else {
    // before webpack 4 there was no chunkGroups
    chunks.forEach(chunk => {
      if (chunk.parents) {
        // Add an edge for each parent (parent -> child)
        chunk.parents.forEach(parentId => {
          // webpack2 chunk.parents are chunks instead of string id(s)
          const parentChunk = _.isObject(parentId) ? parentId : nodeMap[parentId];
          // If the parent chunk does not exist (e.g. because of an excluded chunk)
          // we ignore that parent
          if (parentChunk) {
            edges.push([parentChunk, chunk]);
          }
        });
      }
    });
    // We now perform a topological sorting on the input chunks and built edges
    return toposort.array(chunks, edges);
  }
};

/**
 * Sorts the chunks based on the chunk id.
 *
 * @param  {Array} chunks the list of chunks to sort
 * @return {Array} The sorted list of chunks
 */
module.exports.id = chunks => chunks.sort(function orderEntryLast (a, b) {
  if (a.entry !== b.entry) {
    return b.entry ? 1 : -1;
  } else {
    return b.id - a.id;
  }
});

/**
 * Performs identity mapping (no-sort).
 * @param  {Array} chunks the chunks to sort
 * @return {Array} The sorted chunks
 */
module.exports.none = chunks => chunks;

/**
 * Sort manually by the chunks
 * @param  {Array} chunks the chunks to sort
 * @return {Array} The sorted chunks
 */
module.exports.manual = (chunks, options) => {
  const specifyChunks = options.chunks;
  const chunksResult = [];
  let filterResult = [];
  if (Array.isArray(specifyChunks)) {
    for (var i = 0; i < specifyChunks.length; i++) {
      filterResult = chunks.filter(chunk => {
        if (chunk.names[0] && chunk.names[0] === specifyChunks[i]) {
          return true;
        }
        return false;
      });
      filterResult.length > 0 && chunksResult.push(filterResult[0]);
    }
  }
  return chunksResult;
};

/**
 * Defines the default sorter.
 */
module.exports.auto = module.exports.id;

// In webpack 2 the ids have been flipped.
// Therefore the id sort doesn't work the same way as it did for webpack 1
// Luckily the dependency sort is working as expected
if (Number(require('webpack/package.json').version.split('.')[0]) > 1) {
  module.exports.auto = module.exports.dependency;
}
