import { CancellationToken } from 'vscode-languageserver';
import { Event as Event_2 } from 'vscode-languageserver';
import * as lsp from 'vscode-languageserver-types';
import { Position } from 'vscode-languageserver-types';
import { Range } from 'vscode-languageserver-types';
import { URI } from 'vscode-uri';

/**
 * Information about a parent markdown document that contains sub-documents.
 *
 * This could be a notebook document for example, where the `children` are the Markdown cells in the notebook.
 */
export declare interface ContainingDocumentContext {
    /**
     * Uri of the parent document.
     */
    readonly uri: URI;
    /**
     * List of child markdown documents.
     */
    readonly children: Iterable<{
        readonly uri: URI;
    }>;
}

/**
 * Create a new instance of the {@link IMdLanguageService language service}.
 */
export declare function createLanguageService(init: LanguageServiceInitialization): IMdLanguageService;

/**
 * Error codes of Markdown diagnostics
 */
export declare enum DiagnosticCode {
    /** The linked to reference does not exist. */
    link_noSuchReferences = "link.no-such-reference",
    /** The linked to heading does not exist in the current file. */
    link_noSuchHeaderInOwnFile = "link.no-such-header-in-own-file",
    /** The linked to local file does not exist. */
    link_noSuchFile = "link.no-such-file",
    /** The linked to heading does not exist in the another file. */
    link_noSuchHeaderInFile = "link.no-such-header-in-file",
    /** The link definition is not used anywhere. */
    link_unusedDefinition = "link.unused-definition",
    /** The link definition is not used anywhere. */
    link_duplicateDefinition = "link.duplicate-definition"
}

/**
 * The severity at which diagnostics are reported
 */
export declare enum DiagnosticLevel {
    /** Don't report this diagnostic. */
    ignore = "ignore",
    /**
     * Report the diagnostic at a hint level.
     *
     * Hints will typically not be directly reported by editors, but may show up as unused spans.
     */
    hint = "hint",
    /** Report the diagnostic as a warning. */
    warning = "warning",
    /** Report the diagnostic as an error. */
    error = "error"
}

/**
 * Configure how diagnostics are computed.
 */
export declare interface DiagnosticOptions {
    /**
     * Diagnostic level for invalid reference links, e.g. `[text][no-such-ref]`.
     */
    readonly validateReferences: DiagnosticLevel | undefined;
    /**
     * Diagnostic level for fragments links to headers in the current file that don't exist, e.g. `[text](#no-such-header)`.
     */
    readonly validateFragmentLinks: DiagnosticLevel | undefined;
    /**
     * Diagnostic level for links to local files that don't exist, e.g. `[text](./no-such-file.png)`.
     */
    readonly validateFileLinks: DiagnosticLevel | undefined;
    /**
     * Diagnostic level for the fragment part of links to other local markdown files , e.g. `[text](./file.md#no-such-header)`.
     */
    readonly validateMarkdownFileLinkFragments: DiagnosticLevel | undefined;
    /**
     * Diagnostic level for link definitions that aren't used anywhere. `[never-used]: http://example.com`.
     */
    readonly validateUnusedLinkDefinitions: DiagnosticLevel | undefined;
    /**
     * Diagnostic level for duplicate link definitions.
     */
    readonly validateDuplicateLinkDefinitions: DiagnosticLevel | undefined;
    /**
     * Glob of links that should not be validated.
     */
    readonly ignoreLinks: readonly string[];
}

export declare interface FileRename {
    readonly oldUri: URI;
    readonly newUri: URI;
}

/**
 * Result of {@link IWorkspace.stat stating} a file.
 */
export declare interface FileStat {
    /**
     * True if the file is directory.
     */
    readonly isDirectory: boolean;
}

/**
 * Configures which events a {@link IFileSystemWatcher} fires.
 */
export declare interface FileWatcherOptions {
    /** Ignore file creation events. */
    readonly ignoreCreate?: boolean;
    /** Ignore file change events. */
    readonly ignoreChange?: boolean;
    /** Ignore file delete events. */
    readonly ignoreDelete?: boolean;
}

/**
 * A {@link ISlugifier slugifier} that approximates how GitHub's slugifier works.
 */
export declare const githubSlugifier: ISlugifier;

/**
 * Watches a file for changes to it on the file system.
 */
export declare interface IFileSystemWatcher {
    /**
     * Dispose of the watcher. This should stop watching and clean up any associated resources.
     */
    dispose(): void;
    /** Fired when the file is created. */
    readonly onDidCreate: Event_2<URI>;
    /** Fired when the file is changed on the file system. */
    readonly onDidChange: Event_2<URI>;
    /** Fired when the file is deleted. */
    readonly onDidDelete: Event_2<URI>;
}

/**
 * Logs debug messages from the language service
 */
export declare interface ILogger {
    /**
     * Get the current log level.
     */
    get level(): LogLevel;
    /**
     * Log a message at a given log level.
     *
     * @param level The level the message should be logged at.
     * @param message The main text of the log.
     * @param data Additional information about what is being logged.
     */
    log(level: LogLevel, message: string, data?: Record<string, unknown>): void;
}

/**
 * Provides language tooling methods for working with markdown.
 */
export declare interface IMdLanguageService {
    /**
     * Get all links of a markdown file.
     *
     * Note that you must invoke {@link IMdLanguageService.resolveDocumentLink} on each link before executing the link.
     */
    getDocumentLinks(document: ITextDocument, token: CancellationToken): Promise<lsp.DocumentLink[]>;
    /**
     * Resolves a link from {@link IMdLanguageService.getDocumentLinks}.
     *
     * This fills in the target on the link.
     *
     * @returns The resolved link or `undefined` if the passed in link should be used
     */
    resolveDocumentLink(link: lsp.DocumentLink, token: CancellationToken): Promise<lsp.DocumentLink | undefined>;
    /**
     * Try to resolve the resources that a link in a markdown file points to.
     *
     * @param linkText The original text of the link
     * @param fromResource The resource that contains the link.
     *
     * @returns The resolved target or undefined if it could not be resolved.
     */
    resolveLinkTarget(linkText: string, fromResource: URI, token: CancellationToken): Promise<ResolvedDocumentLinkTarget | undefined>;
    /**
     * Get the symbols of a markdown file.
     *
     * @returns The headers and optionally also the link definitions in the file
     */
    getDocumentSymbols(document: ITextDocument, options: {
        readonly includeLinkDefinitions?: boolean;
    }, token: CancellationToken): Promise<lsp.DocumentSymbol[]>;
    /**
     * Get the folding ranges of a markdown file.
     *
     * This returns folding ranges for:
     *
     * - Header sections
     * - Regions
     * - List and other block element
     */
    getFoldingRanges(document: ITextDocument, token: CancellationToken): Promise<lsp.FoldingRange[]>;
    /**
     * Get the selection ranges of a markdown file.
     */
    getSelectionRanges(document: ITextDocument, positions: lsp.Position[], token: CancellationToken): Promise<lsp.SelectionRange[] | undefined>;
    /**
     * Get the symbols for all markdown files in the current workspace.
     *
     * Returns all headers in the workspace.
     */
    getWorkspaceSymbols(query: string, token: CancellationToken): Promise<lsp.WorkspaceSymbol[]>;
    /**
     * Get completions items at a given position in a markdown file.
     */
    getCompletionItems(document: ITextDocument, position: lsp.Position, context: MdPathCompletionOptions, token: CancellationToken): Promise<lsp.CompletionItem[]>;
    /**
     * Get the references to a symbol at the current location.
     *
     * Supports finding references to headers and links.
     */
    getReferences(document: ITextDocument, position: lsp.Position, context: lsp.ReferenceContext, token: CancellationToken): Promise<lsp.Location[]>;
    /**
     * Get the references to a given file.
     */
    getFileReferences(resource: URI, token: CancellationToken): Promise<lsp.Location[]>;
    /**
     * Get the definition of the symbol at the current location.
     *
     * Supports finding headers from fragments links or reference link definitions.
     */
    getDefinition(document: ITextDocument, position: lsp.Position, token: CancellationToken): Promise<lsp.Definition | undefined>;
    /**
     * Organizes all link definitions in the file by grouping them to the bottom of the file, sorting them, and optionally
     * removing any unused definitions.
     *
     * @returns A set of text edits. May be empty if no edits are required (e.g. the definitions are already sorted at
     * the bottom of the file).
     */
    organizeLinkDefinitions(document: ITextDocument, options: {
        readonly removeUnused?: boolean;
    }, token: CancellationToken): Promise<lsp.TextEdit[]>;
    /**
     * Prepare for showing rename UI.
     *
     * Indicates if rename is supported. If it is, returns the range of symbol being renamed as well as the placeholder to show to the user for the rename.
     */
    prepareRename(document: ITextDocument, position: lsp.Position, token: CancellationToken): Promise<{
        range: lsp.Range;
        placeholder: string;
    } | undefined>;
    /**
     * Get the edits for a rename operation.
     *
     * @returns A workspace edit that performs the rename or undefined if the rename cannot be performed.
     */
    getRenameEdit(document: ITextDocument, position: lsp.Position, nameName: string, token: CancellationToken): Promise<lsp.WorkspaceEdit | undefined>;
    /**
     * Get the edits for a file rename. This update links to the renamed files as well as links within the renamed files.
     *
     * This should be invoked after the rename has already happened (i.e. the workspace should reflect the file system state post rename).
     *
     * You can pass in uris to resources or directories. However if you pass in multiple edits, these edits must not overlap/conflict.
     *
     * @returns An object with a workspace edit that performs the rename and a list of old file uris that effected the edit. Returns undefined if the rename cannot be performed.
     */
    getRenameFilesInWorkspaceEdit(edits: readonly FileRename[], token: CancellationToken): Promise<{
        participatingRenames: readonly FileRename[];
        edit: lsp.WorkspaceEdit;
    } | undefined>;
    /**
     * Get code actions for a selection in a file.
     *
     * Returned code actions may be disabled.
     */
    getCodeActions(document: ITextDocument, range: lsp.Range, context: lsp.CodeActionContext, token: CancellationToken): Promise<lsp.CodeAction[]>;
    /**
     * Get document highlights for a position in the document.
     */
    getDocumentHighlights(document: ITextDocument, position: lsp.Position, token: CancellationToken): Promise<lsp.DocumentHighlight[]>;
    /**
     * Compute diagnostics for a given file.
     *
     * Note that this function is stateless and re-validates all links every time you make the request. Use {@link IMdLanguageService.createPullDiagnosticsManager}
     * to more efficiently get diagnostics.
     */
    computeDiagnostics(doc: ITextDocument, options: DiagnosticOptions, token: CancellationToken): Promise<lsp.Diagnostic[]>;
    /**
     * Create a stateful object that is more efficient at computing diagnostics across repeated calls and workspace changes.
     *
     * This requires a {@link IWorkspace workspace} that {@link IWorkspaceWithWatching supports file watching}.
     *
     * Note that you must dispose of the returned object once you are done using it.
     */
    createPullDiagnosticsManager(): IPullDiagnosticsManager;
    /**
     * Dispose of the language service, freeing any associated resources.
     */
    dispose(): void;
}

/**
 * Parses Markdown text into a stream of tokens.
 */
export declare interface IMdParser {
    /**
     * The {@link ISlugifier slugifier} used for generating unique ids for headers in the Markdown.
     */
    readonly slugifier: ISlugifier;
    /**
     * Parse `document` into a stream of tokens.
     */
    tokenize(document: ITextDocument): Promise<Token[]>;
}

/**
 * Controls if header completions for other files in the workspace be returned.
 */
export declare enum IncludeWorkspaceHeaderCompletions {
    /**
     * Never return workspace header completions.
     */
    never = "never",
    /**
     * Return workspace header completions after `##` is typed.
     *
     * This lets the user signal
     */
    onDoubleHash = "onDoubleHash",
    /**
     * Return workspace header completions after either a single `#` is typed or after `##`
     *
     * For a single hash, this means the workspace header completions will be returned along side the current file header completions.
     */
    onSingleOrDoubleHash = "onSingleOrDoubleHash"
}

/**
 * Stateful object that can more efficiently compute diagnostics for the workspace.
 */
export declare interface IPullDiagnosticsManager {
    /**
     * Dispose of the diagnostic manager and clean up any associated resources.
     */
    dispose(): void;
    /**
     * Event fired when a file that Markdown document is linking to changes.
     */
    readonly onLinkedToFileChanged: Event_2<{
        readonly changedResource: URI;
        readonly linkingResources: readonly URI[];
    }>;
    /**
     * Compute the current diagnostics for a file.
     */
    computeDiagnostics(doc: ITextDocument, options: DiagnosticOptions, token: CancellationToken): Promise<lsp.Diagnostic[]>;
    /**
     * Clean up resources that help provide diagnostics for a document.
     *
     * You should call this when you will no longer be making diagnostic requests for a document, for example
     * when the file has been closed in the editor (but still exists on disk).
     */
    disposeDocumentResources(document: URI): void;
}

/**
 * Generates unique ids for headers in the Markdown.
 */
export declare interface ISlugifier {
    fromHeading(heading: string): Slug;
}

/**
 * A document in the workspace.
 */
export declare interface ITextDocument {
    /**
     * The uri of the document, as a string.
     */
    readonly uri: string;
    /**
     * The uri of the document, as a URI.
     */
    readonly $uri?: URI;
    /**
     * Version number of the document's content.
     */
    readonly version: number;
    /**
     * The total number of lines in the document.
     */
    readonly lineCount: number;
    /**
     * Get text contents of the document.
     *
     * @param range Optional range to get the text of. If not specified, the entire document content is returned.
     */
    getText(range?: Range): string;
    /**
     * Converts an offset in the document into a {@link Position position}.
     */
    positionAt(offset: number): Position;
}

/**
 * Provide information about the contents of a workspace.
 */
export declare interface IWorkspace {
    /**
     * Get the root folders for this workspace.
     */
    get workspaceFolders(): readonly URI[];
    /**
     * Fired when the content of a markdown document changes.
     */
    readonly onDidChangeMarkdownDocument: Event_2<ITextDocument>;
    /**
     * Fired when a markdown document is first created.
     */
    readonly onDidCreateMarkdownDocument: Event_2<ITextDocument>;
    /**
     * Fired when a markdown document is deleted.
     */
    readonly onDidDeleteMarkdownDocument: Event_2<URI>;
    /**
     * Get complete list of markdown documents.
     *
     * This may include documents that have not been opened yet (for example, getAllMarkdownDocuments should
     * return documents from disk even if they have not been opened yet in the editor)
     */
    getAllMarkdownDocuments(): Promise<Iterable<ITextDocument>>;
    /**
     * Check if a document already exists in the workspace contents.
     */
    hasMarkdownDocument(resource: URI): boolean;
    /**
     * Try to open a markdown document.
     *
     * This may either get the document from a cache or open it and add it to the cache.
     *
     * @returns The document, or `undefined` if the file could not be opened or was not a markdown file.
     */
    openMarkdownDocument(resource: URI): Promise<ITextDocument | undefined>;
    /**
     * Get metadata about a file.
     *
     * @param resource URI to check. Does not have to be to a markdown file.
     *
     * @returns Metadata or `undefined` if the resource does not exist.
     */
    stat(resource: URI): Promise<FileStat | undefined>;
    /**
     * List all files in a directory.
     *
     * @param resource URI of the directory to check. Does not have to be to a markdown file.
     *
     * @returns List of `[fileName, metadata]` tuples.
     */
    readDirectory(resource: URI): Promise<Iterable<readonly [string, FileStat]>>;
    /**
     * Get the document that contains `resource` as a sub document.
     *
     * If `resource` is a notebook cell for example, this should return the parent notebook.
     *
     * @returns The parent document info or `undefined` if none.
     */
    getContainingDocument?(resource: URI): ContainingDocumentContext | undefined;
}

/**
 * A workspace that also supports watching arbitrary files.
 */
export declare interface IWorkspaceWithWatching extends IWorkspace {
    /**
     * Start watching a given file.
     */
    watchFile(path: URI, options: FileWatcherOptions): IFileSystemWatcher;
}

/**
 * Initialization options for creating a new {@link IMdLanguageService}.
 */
export declare interface LanguageServiceInitialization extends Partial<LsConfiguration> {
    /**
     * The {@link IWorkspace workspace} that the  {@link IMdLanguageService language service} uses to work with files.
     */
    readonly workspace: IWorkspace;
    /**
     * The {@link IMdParser markdown parsing engine} that the  {@link IMdLanguageService language service} uses to
     * process Markdown source.
     */
    readonly parser: IMdParser;
    /**
     * The {@link ILogger logger} that the  {@link IMdLanguageService language service} use for logging messages.
     */
    readonly logger: ILogger;
}

/**
 * The level of verbosity that the language service logs at.
 */
export declare enum LogLevel {
    /** Disable logging */
    Off = 0,
    /** Log verbose info about language server operation, such as when references are re-computed for a md file. */
    Debug = 1,
    /** Log extremely verbose info about language server operation, such as calls into the file system */
    Trace = 2
}

export declare interface LsConfiguration {
    /**
     * List of file extensions should be considered markdown.
     *
     * These should not include the leading `.`.
     *
     * The first entry is treated as the default file extension.
     */
    readonly markdownFileExtensions: readonly string[];
    /**
     * List of file extension for files that are linked to from markdown .
     *
     * These should not include the leading `.`.
     *
     * These are used to avoid duplicate checks when resolving links without
     * a file extension.
     */
    readonly knownLinkedToFileExtensions: readonly string[];
    /**
     * List of path globs that should be excluded from cross-file operations.
     */
    readonly excludePaths: readonly string[];
    /**
     * Preferred style for file paths to {@link markdownFileExtensions markdown files}.
     *
     * This is used for paths added by the language service, such as for path completions and on file renames.
     */
    readonly preferredMdPathExtensionStyle?: PreferredMdPathExtensionStyle;
}

/**
 * Control the type of path completions returned.
 */
export declare interface MdPathCompletionOptions {
    /**
     * Should header completions for other files in the workspace be returned when
     * you trigger completions.
     *
     * Defaults to {@link IncludeWorkspaceHeaderCompletions.never never} (not returned).
     */
    readonly includeWorkspaceHeaderCompletions?: IncludeWorkspaceHeaderCompletions;
}

/**
 * Preferred style for file paths to {@link markdownFileExtensions markdown files}.
 */
export declare enum PreferredMdPathExtensionStyle {
    /**
     * Try to maintain the existing of the path.
     */
    auto = "auto",
    /**
     * Include the file extension when possible.
     */
    includeExtension = "includeExtension",
    /**
     * Drop the file extension when possible.
     */
    removeExtension = "removeExtension"
}

/**
 * Error thrown when rename is not supported performed at the requested location.
 */
export declare class RenameNotSupportedAtLocationError extends Error {
    constructor();
}

/**
 * The place a document link links to.
 */
export declare type ResolvedDocumentLinkTarget = {
    readonly kind: 'file';
    readonly uri: URI;
    position?: lsp.Position;
    fragment?: string;
} | {
    readonly kind: 'folder';
    readonly uri: URI;
} | {
    readonly kind: 'external';
    readonly uri: URI;
};

declare class Slug {
    readonly value: string;
    constructor(value: string);
    equals(other: Slug): boolean;
}

export declare interface Token {
    readonly type: string;
    readonly markup: string;
    readonly content: string;
    readonly map: number[] | null;
    readonly children: readonly Token[] | null;
}

export { }
