// https://github.com/microsoft/vscode/blob/4c0cecf300334511c6ef64f40ba584dcbe3a03de/src/vs/editor/contrib/documentSymbols/browser/outlineModel.ts
/* ---------------------------------------------------------------------------------------------
 *  Copyright (c) Microsoft Corporation. All rights reserved.
 *  Licensed under the MIT License. See License.txt in the project root for license information.
 *--------------------------------------------------------------------------------------------*/
import type {
  CancellationToken,
  IPosition,
  MarkerSeverity,
  Uri,
  editor,
  languages,
} from "monaco-editor"

export abstract class TreeElement {
  abstract id: string
  abstract children: Map<string, TreeElement>
  abstract parent: TreeElement | undefined

  remove(): void

  static findId(
    candidate: languages.DocumentSymbol | string,
    container: TreeElement,
  ): string
  static getElementById(id: string, element: TreeElement): TreeElement | undefined
  static size(element: TreeElement): number
  static empty(element: TreeElement): boolean
}

export interface IOutlineMarker {
  startLineNumber: number
  startColumn: number
  endLineNumber: number
  endColumn: number
  severity: MarkerSeverity
}

export class OutlineElement extends TreeElement {
  readonly id: string
  readonly symbol: languages.DocumentSymbol
  parent: TreeElement | undefined
  children: Map<string, OutlineElement>
  marker: { count: number; topSev: MarkerSeverity } | undefined

  constructor(
    id: string,
    parent: TreeElement | undefined,
    symbol: languages.DocumentSymbol,
  )
}

export class OutlineGroup extends TreeElement {
  readonly id: string
  public parent: TreeElement | undefined
  readonly label: string
  readonly order: number
  children: Map<string, OutlineElement>

  constructor(id: string, parent: TreeElement | undefined, label: string, order: number)

  getItemEnclosingPosition(position: IPosition): OutlineElement | undefined

  private _getItemEnclosingPosition(
    position: IPosition,
    children: Map<string, OutlineElement>,
  ): OutlineElement | undefined

  updateMarker(marker: IOutlineMarker[]): void

  private _updateMarker(markers: IOutlineMarker[], item: OutlineElement): void
}

export class OutlineModel extends TreeElement {
  static create(
    registry: never, // LanguageFeatureRegistry<languages.DocumentSymbolProvider>,
    textModel: editor.ITextModel,
    token: CancellationToken,
  ): Promise<OutlineModel>

  private static _makeOutlineElement(
    info: languages.DocumentSymbol,
    container: OutlineGroup | OutlineElement,
  ): void

  static get(element: TreeElement | undefined): OutlineModel | undefined

  readonly id: "root"
  readonly parent: undefined

  protected _groups: Map<string, OutlineGroup>
  children: Map<string, OutlineGroup | OutlineElement>

  readonly uri: Uri

  protected constructor(uri: Uri)

  private _compact(): this

  getTopLevelSymbols(): languages.DocumentSymbol[]

  asListOfDocumentSymbols(): languages.DocumentSymbol[]

  private static _flattenDocumentSymbols(
    bucket: languages.DocumentSymbol[],
    entries: languages.DocumentSymbol[],
    overrideContainerLabel: string,
  )
}
