"use strict";
/*---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/

require("core-js/modules/es.symbol.js");

require("core-js/modules/es.symbol.description.js");

require("core-js/modules/es.symbol.iterator.js");

require("core-js/modules/es.array.from.js");

require("core-js/modules/es.array.slice.js");

require("core-js/modules/es.function.name.js");

require("core-js/modules/es.regexp.exec.js");

require("regenerator-runtime/runtime.js");

require("core-js/modules/es.array.sort.js");

require("core-js/modules/es.object.to-string.js");

require("core-js/modules/es.promise.js");

require("core-js/modules/es.string.iterator.js");

require("core-js/modules/es.array.iterator.js");

require("core-js/modules/web.dom-collections.iterator.js");

require("core-js/modules/es.array.filter.js");

function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }

function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }

function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }

function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }

function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }

function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }

function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }

function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.getFoldingRanges = getFoldingRanges;

var languageModes_1 = require("./languageModes");

function getFoldingRanges(_x, _x2, _x3, _x4) {
  return _getFoldingRanges.apply(this, arguments);
}

function _getFoldingRanges() {
  _getFoldingRanges = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee2(languageModes, document, maxRanges, _cancellationToken) {
    var htmlMode, range, result, _result, rangesPerMode, getRangesForMode, modeRanges, _iterator, _step, _loop;

    return regeneratorRuntime.wrap(function _callee2$(_context3) {
      while (1) {
        switch (_context3.prev = _context3.next) {
          case 0:
            htmlMode = languageModes.getMode('html');
            range = languageModes_1.Range.create(languageModes_1.Position.create(0, 0), languageModes_1.Position.create(document.lineCount, 0));
            result = [];

            if (!(htmlMode && htmlMode.getFoldingRanges)) {
              _context3.next = 12;
              break;
            }

            _context3.t0 = (_result = result).push;
            _context3.t1 = _result;
            _context3.t2 = _toConsumableArray;
            _context3.next = 9;
            return htmlMode.getFoldingRanges(document);

          case 9:
            _context3.t3 = _context3.sent;
            _context3.t4 = (0, _context3.t2)(_context3.t3);

            _context3.t0.apply.call(_context3.t0, _context3.t1, _context3.t4);

          case 12:
            // cache folding ranges per mode
            rangesPerMode = Object.create(null);

            getRangesForMode = /*#__PURE__*/function () {
              var _ref = _asyncToGenerator( /*#__PURE__*/regeneratorRuntime.mark(function _callee(mode) {
                var ranges;
                return regeneratorRuntime.wrap(function _callee$(_context) {
                  while (1) {
                    switch (_context.prev = _context.next) {
                      case 0:
                        if (!mode.getFoldingRanges) {
                          _context.next = 11;
                          break;
                        }

                        ranges = rangesPerMode[mode.getId()];

                        if (Array.isArray(ranges)) {
                          _context.next = 10;
                          break;
                        }

                        _context.next = 5;
                        return mode.getFoldingRanges(document);

                      case 5:
                        _context.t0 = _context.sent;

                        if (_context.t0) {
                          _context.next = 8;
                          break;
                        }

                        _context.t0 = [];

                      case 8:
                        ranges = _context.t0;
                        rangesPerMode[mode.getId()] = ranges;

                      case 10:
                        return _context.abrupt("return", ranges);

                      case 11:
                        return _context.abrupt("return", []);

                      case 12:
                      case "end":
                        return _context.stop();
                    }
                  }
                }, _callee);
              }));

              return function getRangesForMode(_x5) {
                return _ref.apply(this, arguments);
              };
            }();

            modeRanges = languageModes.getModesInRange(document, range);
            _iterator = _createForOfIteratorHelper(modeRanges);
            _context3.prev = 16;
            _loop = /*#__PURE__*/regeneratorRuntime.mark(function _loop() {
              var modeRange, mode, _result2, ranges;

              return regeneratorRuntime.wrap(function _loop$(_context2) {
                while (1) {
                  switch (_context2.prev = _context2.next) {
                    case 0:
                      modeRange = _step.value;
                      mode = modeRange.mode;

                      if (!(mode && mode !== htmlMode && !modeRange.attributeValue)) {
                        _context2.next = 7;
                        break;
                      }

                      _context2.next = 5;
                      return getRangesForMode(mode);

                    case 5:
                      ranges = _context2.sent;

                      (_result2 = result).push.apply(_result2, _toConsumableArray(ranges.filter(function (r) {
                        return r.startLine >= modeRange.start.line && r.endLine < modeRange.end.line;
                      })));

                    case 7:
                    case "end":
                      return _context2.stop();
                  }
                }
              }, _loop);
            });

            _iterator.s();

          case 19:
            if ((_step = _iterator.n()).done) {
              _context3.next = 23;
              break;
            }

            return _context3.delegateYield(_loop(), "t5", 21);

          case 21:
            _context3.next = 19;
            break;

          case 23:
            _context3.next = 28;
            break;

          case 25:
            _context3.prev = 25;
            _context3.t6 = _context3["catch"](16);

            _iterator.e(_context3.t6);

          case 28:
            _context3.prev = 28;

            _iterator.f();

            return _context3.finish(28);

          case 31:
            if (maxRanges && result.length > maxRanges) {
              result = limitRanges(result, maxRanges);
            }

            return _context3.abrupt("return", result);

          case 33:
          case "end":
            return _context3.stop();
        }
      }
    }, _callee2, null, [[16, 25, 28, 31]]);
  }));
  return _getFoldingRanges.apply(this, arguments);
}

function limitRanges(ranges, maxRanges) {
  ranges = ranges.sort(function (r1, r2) {
    var diff = r1.startLine - r2.startLine;

    if (diff === 0) {
      diff = r1.endLine - r2.endLine;
    }

    return diff;
  }); // compute each range's nesting level in 'nestingLevels'.
  // count the number of ranges for each level in 'nestingLevelCounts'

  var top = undefined;
  var previous = [];
  var nestingLevels = [];
  var nestingLevelCounts = [];

  var setNestingLevel = function setNestingLevel(index, level) {
    nestingLevels[index] = level;

    if (level < 30) {
      nestingLevelCounts[level] = (nestingLevelCounts[level] || 0) + 1;
    }
  }; // compute nesting levels and sanitize


  for (var i = 0; i < ranges.length; i++) {
    var entry = ranges[i];

    if (!top) {
      top = entry;
      setNestingLevel(i, 0);
    } else {
      if (entry.startLine > top.startLine) {
        if (entry.endLine <= top.endLine) {
          previous.push(top);
          top = entry;
          setNestingLevel(i, previous.length);
        } else if (entry.startLine > top.endLine) {
          do {
            top = previous.pop();
          } while (top && entry.startLine > top.endLine);

          if (top) {
            previous.push(top);
          }

          top = entry;
          setNestingLevel(i, previous.length);
        }
      }
    }
  }

  var entries = 0;
  var maxLevel = 0;

  for (var _i = 0; _i < nestingLevelCounts.length; _i++) {
    var n = nestingLevelCounts[_i];

    if (n) {
      if (n + entries > maxRanges) {
        maxLevel = _i;
        break;
      }

      entries += n;
    }
  }

  var result = [];

  for (var _i2 = 0; _i2 < ranges.length; _i2++) {
    var level = nestingLevels[_i2];

    if (typeof level === 'number') {
      if (level < maxLevel || level === maxLevel && entries++ < maxRanges) {
        result.push(ranges[_i2]);
      }
    }
  }

  return result;
}