"use strict";
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
const arrays = require("../../../../base/common/arrays.js");
const event = require("../../../../base/common/event.js");
const lifecycle = require("../../../../base/common/lifecycle.js");
const linkedList = require("../../../../base/common/linkedList.js");
const strings = require("../../../../base/common/strings.js");
const uri = require("../../../../base/common/uri.js");
const range = require("../../../common/core/range.js");
const extensions = require("../../../../platform/instantiation/common/extensions.js");
const instantiation = require("../../../../platform/instantiation/common/instantiation.js");
const markers = require("../../../../platform/markers/common/markers.js");
const configuration = require("../../../../platform/configuration/common/configuration.js");
var __decorate = globalThis && globalThis.__decorate || function(decorators, target, key, desc) {
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function")
    r = Reflect.decorate(decorators, target, key, desc);
  else
    for (var i = decorators.length - 1; i >= 0; i--)
      if (d = decorators[i])
        r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
  return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __param = globalThis && globalThis.__param || function(paramIndex, decorator) {
  return function(target, key) {
    decorator(target, key, paramIndex);
  };
};
class MarkerCoordinate {
  constructor(marker, index, total) {
    this.marker = marker;
    this.index = index;
    this.total = total;
  }
}
exports.MarkerList = class MarkerList {
  constructor(resourceFilter, _markerService, _configService) {
    this._markerService = _markerService;
    this._configService = _configService;
    this._onDidChange = new event.Emitter();
    this.onDidChange = this._onDidChange.event;
    this._dispoables = new lifecycle.DisposableStore();
    this._markers = [];
    this._nextIdx = -1;
    if (uri.URI.isUri(resourceFilter)) {
      this._resourceFilter = (uri2) => uri2.toString() === resourceFilter.toString();
    } else if (resourceFilter) {
      this._resourceFilter = resourceFilter;
    }
    const compareOrder = this._configService.getValue("problems.sortOrder");
    const compareMarker = (a, b) => {
      let res = strings.compare(a.resource.toString(), b.resource.toString());
      if (res === 0) {
        if (compareOrder === "position") {
          res = range.Range.compareRangesUsingStarts(a, b) || markers.MarkerSeverity.compare(a.severity, b.severity);
        } else {
          res = markers.MarkerSeverity.compare(a.severity, b.severity) || range.Range.compareRangesUsingStarts(a, b);
        }
      }
      return res;
    };
    const updateMarker = () => {
      this._markers = this._markerService.read({
        resource: uri.URI.isUri(resourceFilter) ? resourceFilter : void 0,
        severities: markers.MarkerSeverity.Error | markers.MarkerSeverity.Warning | markers.MarkerSeverity.Info
      });
      if (typeof resourceFilter === "function") {
        this._markers = this._markers.filter((m) => this._resourceFilter(m.resource));
      }
      this._markers.sort(compareMarker);
    };
    updateMarker();
    this._dispoables.add(_markerService.onMarkerChanged((uris) => {
      if (!this._resourceFilter || uris.some((uri2) => this._resourceFilter(uri2))) {
        updateMarker();
        this._nextIdx = -1;
        this._onDidChange.fire();
      }
    }));
  }
  dispose() {
    this._dispoables.dispose();
    this._onDidChange.dispose();
  }
  matches(uri2) {
    if (!this._resourceFilter && !uri2) {
      return true;
    }
    if (!this._resourceFilter || !uri2) {
      return false;
    }
    return this._resourceFilter(uri2);
  }
  get selected() {
    const marker = this._markers[this._nextIdx];
    return marker && new MarkerCoordinate(marker, this._nextIdx + 1, this._markers.length);
  }
  _initIdx(model, position, fwd) {
    let found = false;
    let idx = this._markers.findIndex((marker) => marker.resource.toString() === model.uri.toString());
    if (idx < 0) {
      idx = arrays.binarySearch(this._markers, { resource: model.uri }, (a, b) => strings.compare(a.resource.toString(), b.resource.toString()));
      if (idx < 0) {
        idx = ~idx;
      }
    }
    for (let i = idx; i < this._markers.length; i++) {
      let range$1 = range.Range.lift(this._markers[i]);
      if (range$1.isEmpty()) {
        const word = model.getWordAtPosition(range$1.getStartPosition());
        if (word) {
          range$1 = new range.Range(range$1.startLineNumber, word.startColumn, range$1.startLineNumber, word.endColumn);
        }
      }
      if (position && (range$1.containsPosition(position) || position.isBeforeOrEqual(range$1.getStartPosition()))) {
        this._nextIdx = i;
        found = true;
        break;
      }
      if (this._markers[i].resource.toString() !== model.uri.toString()) {
        break;
      }
    }
    if (!found) {
      this._nextIdx = fwd ? 0 : this._markers.length - 1;
    }
    if (this._nextIdx < 0) {
      this._nextIdx = this._markers.length - 1;
    }
  }
  resetIndex() {
    this._nextIdx = -1;
  }
  move(fwd, model, position) {
    if (this._markers.length === 0) {
      return false;
    }
    let oldIdx = this._nextIdx;
    if (this._nextIdx === -1) {
      this._initIdx(model, position, fwd);
    } else if (fwd) {
      this._nextIdx = (this._nextIdx + 1) % this._markers.length;
    } else if (!fwd) {
      this._nextIdx = (this._nextIdx - 1 + this._markers.length) % this._markers.length;
    }
    if (oldIdx !== this._nextIdx) {
      return true;
    }
    return false;
  }
  find(uri2, position) {
    let idx = this._markers.findIndex((marker) => marker.resource.toString() === uri2.toString());
    if (idx < 0) {
      return void 0;
    }
    for (; idx < this._markers.length; idx++) {
      if (range.Range.containsPosition(this._markers[idx], position)) {
        return new MarkerCoordinate(this._markers[idx], idx + 1, this._markers.length);
      }
    }
    return void 0;
  }
};
exports.MarkerList = __decorate([
  __param(1, markers.IMarkerService),
  __param(2, configuration.IConfigurationService)
], exports.MarkerList);
const IMarkerNavigationService = instantiation.createDecorator("IMarkerNavigationService");
let MarkerNavigationService = class MarkerNavigationService2 {
  constructor(_markerService, _configService) {
    this._markerService = _markerService;
    this._configService = _configService;
    this._provider = new linkedList.LinkedList();
  }
  getMarkerList(resource) {
    for (let provider of this._provider) {
      const result = provider.getMarkerList(resource);
      if (result) {
        return result;
      }
    }
    return new exports.MarkerList(resource, this._markerService, this._configService);
  }
};
MarkerNavigationService = __decorate([
  __param(0, markers.IMarkerService),
  __param(1, configuration.IConfigurationService)
], MarkerNavigationService);
extensions.registerSingleton(IMarkerNavigationService, MarkerNavigationService, true);
exports.IMarkerNavigationService = IMarkerNavigationService;
exports.MarkerCoordinate = MarkerCoordinate;
