"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.ConfigurationModel = exports.Configuration = void 0;
const tslib_1 = require("tslib");
const cloneDeep_1 = tslib_1.__importDefault(require("lodash/cloneDeep"));
const ide_core_common_1 = require("@opensumi/ide-core-common");
class Configuration {
    constructor(defaultConfiguration, userConfiguration, workspaceConfiguration = new ConfigurationModel(), folderConfigurations = {}) {
        this.defaultConfiguration = defaultConfiguration;
        this.userConfiguration = userConfiguration;
        this.workspaceConfiguration = workspaceConfiguration;
        this.folderConfigurations = folderConfigurations;
        this.folderCombinedConfigs = {};
    }
    getValue(section, workspace, resource) {
        return this.getCombinedResourceConfig(workspace, resource).getValue(section);
    }
    inspect(key, workspace, resource) {
        const combinedConfiguration = this.getCombinedResourceConfig(workspace, resource);
        const folderConfiguration = this.getFolderResourceConfig(workspace, resource);
        return {
            default: this.defaultConfiguration.getValue(key),
            user: this.userConfiguration.getValue(key),
            workspace: workspace ? this.workspaceConfiguration.getValue(key) : void 0,
            workspaceFolder: folderConfiguration ? folderConfiguration.getValue(key) : void 0,
            value: combinedConfiguration.getValue(key),
        };
    }
    getCombinedResourceConfig(workspace, resource) {
        const combinedConfig = this.getCombinedConfig();
        if (!workspace || !resource) {
            return combinedConfig;
        }
        const workspaceFolder = workspace.getWorkspaceFolder(resource);
        if (!workspaceFolder) {
            return combinedConfig;
        }
        return this.getFolderCombinedConfig(workspaceFolder.uri.toString()) || combinedConfig;
    }
    getCombinedConfig() {
        if (!this.combinedConfig) {
            this.combinedConfig = this.defaultConfiguration.merge(this.userConfiguration, this.workspaceConfiguration);
        }
        return this.combinedConfig;
    }
    getFolderCombinedConfig(folder) {
        if (this.folderCombinedConfigs[folder]) {
            return this.folderCombinedConfigs[folder];
        }
        const combinedConfig = this.getCombinedConfig();
        const folderConfig = this.folderConfigurations[folder];
        if (!folderConfig) {
            return combinedConfig;
        }
        const folderCombinedConfig = combinedConfig.merge(folderConfig);
        this.folderCombinedConfigs[folder] = folderCombinedConfig;
        return folderCombinedConfig;
    }
    getFolderResourceConfig(workspace, resource) {
        if (!workspace || !resource) {
            return;
        }
        const workspaceFolder = workspace.getWorkspaceFolder(resource);
        if (!workspaceFolder) {
            return;
        }
        return this.folderConfigurations[workspaceFolder.uri.toString()];
    }
}
exports.Configuration = Configuration;
class ConfigurationModel {
    constructor(contents = {}, keys = []) {
        this.contents = contents;
        this.keys = keys;
    }
    getValue(section) {
        if (!section) {
            return this.contents;
        }
        const paths = section.split('.');
        let current = this.contents;
        for (const path of paths) {
            if (typeof current !== 'object' || current === null) {
                return undefined;
            }
            current = current[path];
        }
        return current;
    }
    merge(...others) {
        const contents = (0, cloneDeep_1.default)(this.contents);
        const allKeys = [...this.keys];
        for (const other of others) {
            this.mergeContents(contents, other.contents);
            this.mergeKeys(allKeys, other.keys);
        }
        return new ConfigurationModel(contents, allKeys);
    }
    mergeContents(source, target) {
        for (const key of Object.keys(target)) {
            if (key in source) {
                if ((0, ide_core_common_1.isObject)(source[key]) && (0, ide_core_common_1.isObject)(target[key])) {
                    this.mergeContents(source[key], target[key]);
                    continue;
                }
            }
            source[key] = (0, cloneDeep_1.default)(target[key]);
        }
    }
    mergeKeys(source, target) {
        for (const key of target) {
            if (source.indexOf(key) === -1) {
                source.push(key);
            }
        }
    }
}
exports.ConfigurationModel = ConfigurationModel;
//# sourceMappingURL=configuration.js.map