'use strict';

var barycenter = require('./barycenter.js');
var resolveConflicts = require('./resolve-conflicts.js');
var sort = require('./sort.js');
var filter = require('../../../../../../lodash-es@4.17.21/node_modules/lodash-es/filter.js');
var forEach = require('../../../../../../lodash-es@4.17.21/node_modules/lodash-es/forEach.js');
var flatten = require('../../../../../../lodash-es@4.17.21/node_modules/lodash-es/flatten.js');
var isUndefined = require('../../../../../../lodash-es@4.17.21/node_modules/lodash-es/isUndefined.js');

function sortSubgraph(g, v, cg, biasRight) {
  var movable = g.children(v);
  var node = g.node(v);
  var bl = node ? node.borderLeft : undefined;
  var br = node ? node.borderRight : undefined;
  var subgraphs = {};

  if (bl) {
    movable = filter(movable, function (w) {
      return w !== bl && w !== br;
    });
  }

  var barycenters = barycenter.barycenter(g, movable);
  forEach(barycenters, function (entry) {
    if (g.children(entry.v).length) {
      var subgraphResult = sortSubgraph(g, entry.v, cg, biasRight);
      subgraphs[entry.v] = subgraphResult;
      if (Object.prototype.hasOwnProperty.call(subgraphResult, 'barycenter')) {
        mergeBarycenters(entry, subgraphResult);
      }
    }
  });

  var entries = resolveConflicts.resolveConflicts(barycenters, cg);
  expandSubgraphs(entries, subgraphs);

  var result = sort.sort(entries, biasRight);

  if (bl) {
    result.vs = flatten([bl, result.vs, br]);
    if (g.predecessors(bl).length) {
      var blPred = g.node(g.predecessors(bl)[0]),
        brPred = g.node(g.predecessors(br)[0]);
      if (!Object.prototype.hasOwnProperty.call(result, 'barycenter')) {
        result.barycenter = 0;
        result.weight = 0;
      }
      result.barycenter =
        (result.barycenter * result.weight + blPred.order + brPred.order) / (result.weight + 2);
      result.weight += 2;
    }
  }

  return result;
}

function expandSubgraphs(entries, subgraphs) {
  forEach(entries, function (entry) {
    entry.vs = flatten(
      entry.vs.map(function (v) {
        if (subgraphs[v]) {
          return subgraphs[v].vs;
        }
        return v;
      }),
    );
  });
}

function mergeBarycenters(target, other) {
  if (!isUndefined(target.barycenter)) {
    target.barycenter =
      (target.barycenter * target.weight + other.barycenter * other.weight) /
      (target.weight + other.weight);
    target.weight += other.weight;
  } else {
    target.barycenter = other.barycenter;
    target.weight = other.weight;
  }
}

exports.sortSubgraph = sortSubgraph;
