
import { TernarySearchTree } from '../../../base/common/ternarySearchTree.js';
import '../../../base/common/path.js';
import '../../../base/common/strings.js';
import { isNumber } from '../../../base/common/types.js';
import { URI } from '../../../base/common/uri.js';
import { localize } from '../../../nls.js';
import { isWeb } from '../../../base/common/platform.js';
import { Schemas } from '../../../base/common/network.js';
import { Lazy } from '../../../base/common/lazy.js';

var FileType;
(function (FileType) {
    FileType[FileType["Unknown"] = 0] = "Unknown";
    FileType[FileType["File"] = 1] = "File";
    FileType[FileType["Directory"] = 2] = "Directory";
    FileType[FileType["SymbolicLink"] = 64] = "SymbolicLink";
})(FileType || (FileType = {}));
var FilePermission;
(function (FilePermission) {
    FilePermission[FilePermission["Readonly"] = 1] = "Readonly";
    FilePermission[FilePermission["Locked"] = 2] = "Locked";
})(FilePermission || (FilePermission = {}));
var FileChangeFilter;
(function (FileChangeFilter) {
    FileChangeFilter[FileChangeFilter["UPDATED"] = 2] = "UPDATED";
    FileChangeFilter[FileChangeFilter["ADDED"] = 4] = "ADDED";
    FileChangeFilter[FileChangeFilter["DELETED"] = 8] = "DELETED";
})(FileChangeFilter || (FileChangeFilter = {}));
var FileSystemProviderCapabilities;
(function (FileSystemProviderCapabilities) {
    FileSystemProviderCapabilities[FileSystemProviderCapabilities["None"] = 0] = "None";
    FileSystemProviderCapabilities[FileSystemProviderCapabilities["FileReadWrite"] = 2] = "FileReadWrite";
    FileSystemProviderCapabilities[FileSystemProviderCapabilities["FileOpenReadWriteClose"] = 4] = "FileOpenReadWriteClose";
    FileSystemProviderCapabilities[FileSystemProviderCapabilities["FileReadStream"] = 16] = "FileReadStream";
    FileSystemProviderCapabilities[FileSystemProviderCapabilities["FileFolderCopy"] = 8] = "FileFolderCopy";
    FileSystemProviderCapabilities[FileSystemProviderCapabilities["PathCaseSensitive"] = 1024] = "PathCaseSensitive";
    FileSystemProviderCapabilities[FileSystemProviderCapabilities["Readonly"] = 2048] = "Readonly";
    FileSystemProviderCapabilities[FileSystemProviderCapabilities["Trash"] = 4096] = "Trash";
    FileSystemProviderCapabilities[FileSystemProviderCapabilities["FileWriteUnlock"] = 8192] = "FileWriteUnlock";
    FileSystemProviderCapabilities[FileSystemProviderCapabilities["FileAtomicRead"] = 16384] = "FileAtomicRead";
    FileSystemProviderCapabilities[FileSystemProviderCapabilities["FileAtomicWrite"] = 32768] = "FileAtomicWrite";
    FileSystemProviderCapabilities[FileSystemProviderCapabilities["FileAtomicDelete"] = 65536] = "FileAtomicDelete";
    FileSystemProviderCapabilities[FileSystemProviderCapabilities["FileClone"] = 131072] = "FileClone";
})(FileSystemProviderCapabilities || (FileSystemProviderCapabilities = {}));
function hasReadWriteCapability(provider) {
    return !!(provider.capabilities & FileSystemProviderCapabilities.FileReadWrite);
}
function hasFileFolderCopyCapability(provider) {
    return !!(provider.capabilities & FileSystemProviderCapabilities.FileFolderCopy);
}
function hasFileCloneCapability(provider) {
    return !!(provider.capabilities & FileSystemProviderCapabilities.FileClone);
}
function hasOpenReadWriteCloseCapability(provider) {
    return !!(provider.capabilities & FileSystemProviderCapabilities.FileOpenReadWriteClose);
}
function hasFileReadStreamCapability(provider) {
    return !!(provider.capabilities & FileSystemProviderCapabilities.FileReadStream);
}
function hasFileAtomicReadCapability(provider) {
    if (!hasReadWriteCapability(provider)) {
        return false;
    }
    return !!(provider.capabilities & FileSystemProviderCapabilities.FileAtomicRead);
}
function hasFileAtomicWriteCapability(provider) {
    if (!hasReadWriteCapability(provider)) {
        return false;
    }
    return !!(provider.capabilities & FileSystemProviderCapabilities.FileAtomicWrite);
}
function hasFileAtomicDeleteCapability(provider) {
    return !!(provider.capabilities & FileSystemProviderCapabilities.FileAtomicDelete);
}
function hasReadonlyCapability(provider) {
    return !!(provider.capabilities & FileSystemProviderCapabilities.Readonly);
}
var FileSystemProviderErrorCode;
(function (FileSystemProviderErrorCode) {
    FileSystemProviderErrorCode["FileExists"] = "EntryExists";
    FileSystemProviderErrorCode["FileNotFound"] = "EntryNotFound";
    FileSystemProviderErrorCode["FileNotADirectory"] = "EntryNotADirectory";
    FileSystemProviderErrorCode["FileIsADirectory"] = "EntryIsADirectory";
    FileSystemProviderErrorCode["FileExceedsStorageQuota"] = "EntryExceedsStorageQuota";
    FileSystemProviderErrorCode["FileTooLarge"] = "EntryTooLarge";
    FileSystemProviderErrorCode["FileWriteLocked"] = "EntryWriteLocked";
    FileSystemProviderErrorCode["NoPermissions"] = "NoPermissions";
    FileSystemProviderErrorCode["Unavailable"] = "Unavailable";
    FileSystemProviderErrorCode["Unknown"] = "Unknown";
})(FileSystemProviderErrorCode || (FileSystemProviderErrorCode = {}));
class FileSystemProviderError extends Error {
    static create(error, code) {
        const providerError = ( new FileSystemProviderError(( error.toString()), code));
        markAsFileSystemProviderError(providerError, code);
        return providerError;
    }
    constructor(message, code) {
        super(message);
        this.code = code;
    }
}
function createFileSystemProviderError(error, code) {
    return FileSystemProviderError.create(error, code);
}
function ensureFileSystemProviderError(error) {
    if (!error) {
        return createFileSystemProviderError(( localize(1878, "Unknown Error")), FileSystemProviderErrorCode.Unknown);
    }
    return error;
}
function markAsFileSystemProviderError(error, code) {
    error.name = code ? `${code} (FileSystemError)` : `FileSystemError`;
    return error;
}
function toFileSystemProviderErrorCode(error) {
    if (!error) {
        return FileSystemProviderErrorCode.Unknown;
    }
    if (error instanceof FileSystemProviderError) {
        return error.code;
    }
    const match = /^(.+) \(FileSystemError\)$/.exec(error.name);
    if (!match) {
        return FileSystemProviderErrorCode.Unknown;
    }
    switch (match[1]) {
        case FileSystemProviderErrorCode.FileExists: return FileSystemProviderErrorCode.FileExists;
        case FileSystemProviderErrorCode.FileIsADirectory: return FileSystemProviderErrorCode.FileIsADirectory;
        case FileSystemProviderErrorCode.FileNotADirectory: return FileSystemProviderErrorCode.FileNotADirectory;
        case FileSystemProviderErrorCode.FileNotFound: return FileSystemProviderErrorCode.FileNotFound;
        case FileSystemProviderErrorCode.FileTooLarge: return FileSystemProviderErrorCode.FileTooLarge;
        case FileSystemProviderErrorCode.FileWriteLocked: return FileSystemProviderErrorCode.FileWriteLocked;
        case FileSystemProviderErrorCode.NoPermissions: return FileSystemProviderErrorCode.NoPermissions;
        case FileSystemProviderErrorCode.Unavailable: return FileSystemProviderErrorCode.Unavailable;
    }
    return FileSystemProviderErrorCode.Unknown;
}
function toFileOperationResult(error) {
    if (error instanceof FileOperationError) {
        return error.fileOperationResult;
    }
    switch (toFileSystemProviderErrorCode(error)) {
        case FileSystemProviderErrorCode.FileNotFound:
            return FileOperationResult.FILE_NOT_FOUND;
        case FileSystemProviderErrorCode.FileIsADirectory:
            return FileOperationResult.FILE_IS_DIRECTORY;
        case FileSystemProviderErrorCode.FileNotADirectory:
            return FileOperationResult.FILE_NOT_DIRECTORY;
        case FileSystemProviderErrorCode.FileWriteLocked:
            return FileOperationResult.FILE_WRITE_LOCKED;
        case FileSystemProviderErrorCode.NoPermissions:
            return FileOperationResult.FILE_PERMISSION_DENIED;
        case FileSystemProviderErrorCode.FileExists:
            return FileOperationResult.FILE_MOVE_CONFLICT;
        case FileSystemProviderErrorCode.FileTooLarge:
            return FileOperationResult.FILE_TOO_LARGE;
        default:
            return FileOperationResult.FILE_OTHER_ERROR;
    }
}
var FileOperation;
(function (FileOperation) {
    FileOperation[FileOperation["CREATE"] = 0] = "CREATE";
    FileOperation[FileOperation["DELETE"] = 1] = "DELETE";
    FileOperation[FileOperation["MOVE"] = 2] = "MOVE";
    FileOperation[FileOperation["COPY"] = 3] = "COPY";
    FileOperation[FileOperation["WRITE"] = 4] = "WRITE";
})(FileOperation || (FileOperation = {}));
class FileOperationEvent {
    constructor(resource, operation, target) {
        this.resource = resource;
        this.operation = operation;
        this.target = target;
    }
    isOperation(operation) {
        return this.operation === operation;
    }
}
var FileChangeType;
(function (FileChangeType) {
    FileChangeType[FileChangeType["UPDATED"] = 0] = "UPDATED";
    FileChangeType[FileChangeType["ADDED"] = 1] = "ADDED";
    FileChangeType[FileChangeType["DELETED"] = 2] = "DELETED";
})(FileChangeType || (FileChangeType = {}));
class FileChangesEvent {
    static { this.MIXED_CORRELATION = null; }
    constructor(changes, ignorePathCasing) {
        this.ignorePathCasing = ignorePathCasing;
        this.correlationId = undefined;
        this.added = ( new Lazy(() => {
            const added = TernarySearchTree.forUris(() => this.ignorePathCasing);
            added.fill(( this.rawAdded.map(resource => [resource, true])));
            return added;
        }));
        this.updated = ( new Lazy(() => {
            const updated = TernarySearchTree.forUris(() => this.ignorePathCasing);
            updated.fill(( this.rawUpdated.map(resource => [resource, true])));
            return updated;
        }));
        this.deleted = ( new Lazy(() => {
            const deleted = TernarySearchTree.forUris(() => this.ignorePathCasing);
            deleted.fill(( this.rawDeleted.map(resource => [resource, true])));
            return deleted;
        }));
        this.rawAdded = [];
        this.rawUpdated = [];
        this.rawDeleted = [];
        for (const change of changes) {
            switch (change.type) {
                case FileChangeType.ADDED:
                    this.rawAdded.push(change.resource);
                    break;
                case FileChangeType.UPDATED:
                    this.rawUpdated.push(change.resource);
                    break;
                case FileChangeType.DELETED:
                    this.rawDeleted.push(change.resource);
                    break;
            }
            if (this.correlationId !== FileChangesEvent.MIXED_CORRELATION) {
                if (typeof change.cId === 'number') {
                    if (this.correlationId === undefined) {
                        this.correlationId = change.cId;
                    }
                    else if (this.correlationId !== change.cId) {
                        this.correlationId = FileChangesEvent.MIXED_CORRELATION;
                    }
                }
                else {
                    if (this.correlationId !== undefined) {
                        this.correlationId = FileChangesEvent.MIXED_CORRELATION;
                    }
                }
            }
        }
    }
    contains(resource, ...types) {
        return this.doContains(resource, { includeChildren: false }, ...types);
    }
    affects(resource, ...types) {
        return this.doContains(resource, { includeChildren: true }, ...types);
    }
    doContains(resource, options, ...types) {
        if (!resource) {
            return false;
        }
        const hasTypesFilter = types.length > 0;
        if (!hasTypesFilter || types.includes(FileChangeType.ADDED)) {
            if (this.added.value.get(resource)) {
                return true;
            }
            if (options.includeChildren && this.added.value.findSuperstr(resource)) {
                return true;
            }
        }
        if (!hasTypesFilter || types.includes(FileChangeType.UPDATED)) {
            if (this.updated.value.get(resource)) {
                return true;
            }
            if (options.includeChildren && this.updated.value.findSuperstr(resource)) {
                return true;
            }
        }
        if (!hasTypesFilter || types.includes(FileChangeType.DELETED)) {
            if (this.deleted.value.findSubstr(resource) ) {
                return true;
            }
            if (options.includeChildren && this.deleted.value.findSuperstr(resource)) {
                return true;
            }
        }
        return false;
    }
    gotAdded() {
        return this.rawAdded.length > 0;
    }
    gotDeleted() {
        return this.rawDeleted.length > 0;
    }
    gotUpdated() {
        return this.rawUpdated.length > 0;
    }
    correlates(correlationId) {
        return this.correlationId === correlationId;
    }
    hasCorrelation() {
        return typeof this.correlationId === 'number';
    }
}
class FileOperationError extends Error {
    constructor(message, fileOperationResult, options) {
        super(message);
        this.fileOperationResult = fileOperationResult;
        this.options = options;
    }
}
class TooLargeFileOperationError extends FileOperationError {
    constructor(message, fileOperationResult, size, options) {
        super(message, fileOperationResult, options);
        this.fileOperationResult = fileOperationResult;
        this.size = size;
    }
}
class NotModifiedSinceFileOperationError extends FileOperationError {
    constructor(message, stat, options) {
        super(message, FileOperationResult.FILE_NOT_MODIFIED_SINCE, options);
        this.stat = stat;
    }
}
var FileOperationResult;
(function (FileOperationResult) {
    FileOperationResult[FileOperationResult["FILE_IS_DIRECTORY"] = 0] = "FILE_IS_DIRECTORY";
    FileOperationResult[FileOperationResult["FILE_NOT_FOUND"] = 1] = "FILE_NOT_FOUND";
    FileOperationResult[FileOperationResult["FILE_NOT_MODIFIED_SINCE"] = 2] = "FILE_NOT_MODIFIED_SINCE";
    FileOperationResult[FileOperationResult["FILE_MODIFIED_SINCE"] = 3] = "FILE_MODIFIED_SINCE";
    FileOperationResult[FileOperationResult["FILE_MOVE_CONFLICT"] = 4] = "FILE_MOVE_CONFLICT";
    FileOperationResult[FileOperationResult["FILE_WRITE_LOCKED"] = 5] = "FILE_WRITE_LOCKED";
    FileOperationResult[FileOperationResult["FILE_PERMISSION_DENIED"] = 6] = "FILE_PERMISSION_DENIED";
    FileOperationResult[FileOperationResult["FILE_TOO_LARGE"] = 7] = "FILE_TOO_LARGE";
    FileOperationResult[FileOperationResult["FILE_INVALID_PATH"] = 8] = "FILE_INVALID_PATH";
    FileOperationResult[FileOperationResult["FILE_NOT_DIRECTORY"] = 9] = "FILE_NOT_DIRECTORY";
    FileOperationResult[FileOperationResult["FILE_OTHER_ERROR"] = 10] = "FILE_OTHER_ERROR";
})(FileOperationResult || (FileOperationResult = {}));
const AutoSaveConfiguration = {
    OFF: 'off',
    AFTER_DELAY: 'afterDelay',
    ON_FOCUS_CHANGE: 'onFocusChange',
    ON_WINDOW_CHANGE: 'onWindowChange'
};
const HotExitConfiguration = {
    OFF: 'off',
    ON_EXIT: 'onExit',
    ON_EXIT_AND_WINDOW_CLOSE: 'onExitAndWindowClose'
};
const FILES_ASSOCIATIONS_CONFIG = 'files.associations';
const FILES_EXCLUDE_CONFIG = 'files.exclude';
const FILES_READONLY_INCLUDE_CONFIG = 'files.readonlyInclude';
const FILES_READONLY_EXCLUDE_CONFIG = 'files.readonlyExclude';
const FILES_READONLY_FROM_PERMISSIONS_CONFIG = 'files.readonlyFromPermissions';
var FileKind;
(function (FileKind) {
    FileKind[FileKind["FILE"] = 0] = "FILE";
    FileKind[FileKind["FOLDER"] = 1] = "FOLDER";
    FileKind[FileKind["ROOT_FOLDER"] = 2] = "ROOT_FOLDER";
})(FileKind || (FileKind = {}));
const ETAG_DISABLED = '';
function etag(stat) {
    if (typeof stat.size !== 'number' || typeof stat.mtime !== 'number') {
        return undefined;
    }
    return ( stat.mtime.toString(29)) + ( stat.size.toString(31));
}
async function whenProviderRegistered(file, fileService) {
    if (fileService.hasProvider(( URI.from({ scheme: file.scheme })))) {
        return;
    }
    return ( new Promise(resolve => {
        const disposable = fileService.onDidChangeFileSystemProviderRegistrations(e => {
            if (e.scheme === file.scheme && e.added) {
                disposable.dispose();
                resolve();
            }
        });
    }));
}
class ByteSize {
    static { this.KB = 1024; }
    static { this.MB = ByteSize.KB * ByteSize.KB; }
    static { this.GB = ByteSize.MB * ByteSize.KB; }
    static { this.TB = ByteSize.GB * ByteSize.KB; }
    static formatSize(size) {
        if (!isNumber(size)) {
            size = 0;
        }
        if (size < ByteSize.KB) {
            return localize(1879, "{0}B", size.toFixed(0));
        }
        if (size < ByteSize.MB) {
            return localize(1880, "{0}KB", (size / ByteSize.KB).toFixed(2));
        }
        if (size < ByteSize.GB) {
            return localize(1881, "{0}MB", (size / ByteSize.MB).toFixed(2));
        }
        if (size < ByteSize.TB) {
            return localize(1882, "{0}GB", (size / ByteSize.GB).toFixed(2));
        }
        return localize(1883, "{0}TB", (size / ByteSize.TB).toFixed(2));
    }
}
function getLargeFileConfirmationLimit(arg) {
    const isRemote = typeof arg === 'string' || arg?.scheme === Schemas.vscodeRemote;
    const isLocal = typeof arg !== 'string' && arg?.scheme === Schemas.file;
    if (isLocal) {
        return 1024 * ByteSize.MB;
    }
    if (isRemote) {
        return 10 * ByteSize.MB;
    }
    if (isWeb) {
        return 50 * ByteSize.MB;
    }
    return 1024 * ByteSize.MB;
}

export { AutoSaveConfiguration, ByteSize, ETAG_DISABLED, FILES_ASSOCIATIONS_CONFIG, FILES_EXCLUDE_CONFIG, FILES_READONLY_EXCLUDE_CONFIG, FILES_READONLY_FROM_PERMISSIONS_CONFIG, FILES_READONLY_INCLUDE_CONFIG, FileChangeFilter, FileChangeType, FileChangesEvent, FileKind, FileOperation, FileOperationError, FileOperationEvent, FileOperationResult, FilePermission, FileSystemProviderCapabilities, FileSystemProviderError, FileSystemProviderErrorCode, FileType, HotExitConfiguration, NotModifiedSinceFileOperationError, TooLargeFileOperationError, createFileSystemProviderError, ensureFileSystemProviderError, etag, getLargeFileConfirmationLimit, hasFileAtomicDeleteCapability, hasFileAtomicReadCapability, hasFileAtomicWriteCapability, hasFileCloneCapability, hasFileFolderCopyCapability, hasFileReadStreamCapability, hasOpenReadWriteCloseCapability, hasReadWriteCapability, hasReadonlyCapability, markAsFileSystemProviderError, toFileOperationResult, toFileSystemProviderErrorCode, whenProviderRegistered };
