"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Decoration = exports.TargetMatchMode = void 0;
const ide_utils_1 = require("@opensumi/ide-utils");
const TreeNode_1 = require("../TreeNode");
var TargetMatchMode;
(function (TargetMatchMode) {
    TargetMatchMode[TargetMatchMode["None"] = 1] = "None";
    // 样式作用于自身
    TargetMatchMode[TargetMatchMode["Self"] = 2] = "Self";
    // 样式作用于子元素
    TargetMatchMode[TargetMatchMode["Children"] = 3] = "Children";
    // 样式作用于自身及子元素
    TargetMatchMode[TargetMatchMode["SelfAndChildren"] = 4] = "SelfAndChildren";
})(TargetMatchMode = exports.TargetMatchMode || (exports.TargetMatchMode = {}));
class Decoration {
    constructor(...cssClassList) {
        this._appliedTargets = new Map();
        this._negatedTargets = new Map();
        this._disabled = false;
        this.appliedTargetsDisposables = new WeakMap();
        this.negatedTargetsDisposables = new WeakMap();
        this.onDidAddCSSClassnameEmitter = new ide_utils_1.Emitter();
        this.onDidRemoveCSSClassnameEmitter = new ide_utils_1.Emitter();
        this.onDidDisableDecorationEmitter = new ide_utils_1.Emitter();
        this.onDidEnableDecorationEmitter = new ide_utils_1.Emitter();
        this.onDidAddTargetEmitter = new ide_utils_1.Emitter();
        this.onDidRemoveTargetEmitter = new ide_utils_1.Emitter();
        this.onDidNegateTargetEmitter = new ide_utils_1.Emitter();
        this.onDidUnNegateTargetEmitter = new ide_utils_1.Emitter();
        if (Array.isArray(cssClassList)) {
            if (cssClassList.every((classname) => typeof classname === 'string')) {
                this._cssClassList = new Set(cssClassList);
            }
            else {
                throw new TypeError('classlist must be of type `Array<string>`');
            }
        }
        else {
            this._cssClassList = new Set();
        }
    }
    get disabled() {
        return this._disabled;
    }
    set disabled(disabled) {
        this._disabled = disabled;
        if (disabled) {
            this.onDidDisableDecorationEmitter.fire({ decoration: this });
        }
        else {
            this.onDidEnableDecorationEmitter.fire({ decoration: this });
        }
    }
    get appliedTargets() {
        return this._appliedTargets;
    }
    get negatedTargets() {
        return this._negatedTargets;
    }
    get cssClassList() {
        return this._cssClassList;
    }
    get onDidAddCSSClassname() {
        return this.onDidAddCSSClassnameEmitter.event;
    }
    get onDidRemoveCSSClassname() {
        return this.onDidRemoveCSSClassnameEmitter.event;
    }
    get onDidDisableDecoration() {
        return this.onDidDisableDecorationEmitter.event;
    }
    get onDidEnableDecoration() {
        return this.onDidEnableDecorationEmitter.event;
    }
    get onDidAddTarget() {
        return this.onDidAddTargetEmitter.event;
    }
    get onDidRemoveTarget() {
        return this.onDidRemoveTargetEmitter.event;
    }
    get onDidNegateTarget() {
        return this.onDidNegateTargetEmitter.event;
    }
    get onDidUnNegateTarget() {
        return this.onDidUnNegateTargetEmitter.event;
    }
    addCSSClass(className) {
        if (this._cssClassList.has(className)) {
            return;
        }
        this._cssClassList.add(className);
        this.onDidAddCSSClassnameEmitter.fire({ decoration: this, classname: className });
    }
    removeCSSClass(className) {
        if (!this._cssClassList.has(className)) {
            return;
        }
        this._cssClassList.delete(className);
        this.onDidRemoveCSSClassnameEmitter.fire({ decoration: this, classname: className });
    }
    /**
     * 判断当前装饰器是否包含指定的对象绑定
     * @param target
     */
    hasTarget(target) {
        const existingFlags = this._appliedTargets.get(target);
        return !!existingFlags;
    }
    /**
     * 为当前装饰器绑定对象
     * @param target
     * @param flags
     */
    addTarget(target, flags = TargetMatchMode.Self) {
        const existingFlags = this._appliedTargets.get(target);
        if (existingFlags === flags) {
            return;
        }
        if (!TreeNode_1.TreeNode.is(target)) {
            return;
        }
        this._appliedTargets.set(target, flags);
        const dispose = ide_utils_1.Disposable.create(() => {
            this.removeTarget(target);
        });
        this.appliedTargetsDisposables.set(target, dispose);
        this.onDidAddTargetEmitter.fire({ decoration: this, target });
        return dispose;
    }
    /**
     * 为当前装饰器移除对象绑定
     * @param target
     * @param flags
     */
    removeTarget(target) {
        if (this._appliedTargets.delete(target)) {
            const disposable = this.appliedTargetsDisposables.get(target);
            if (disposable) {
                disposable.dispose();
            }
            this.onDidRemoveTargetEmitter.fire({ decoration: this, target });
        }
    }
    /**
     * 清理所有应用的装饰器
     */
    clearAppliedTarget() {
        const appliedTargets = Array.from(this._appliedTargets.keys());
        for (const target of appliedTargets) {
            this.removeTarget(target);
        }
    }
    /**
     * 清理所有应用的否定装饰器
     */
    clearNegateTarget() {
        const negatedTargets = Array.from(this._negatedTargets.keys());
        for (const target of negatedTargets) {
            this.unNegateTarget(target);
        }
    }
    /**
     * 否定装饰器绑定
     * negate 表示 :not修饰符
     * 定义节点不应用样式
     * @param target
     * @param flags
     */
    negateTarget(target, flags = TargetMatchMode.Self) {
        const existingFlags = this._negatedTargets.get(target);
        if (existingFlags === flags) {
            return;
        }
        if (!TreeNode_1.TreeNode.is(target)) {
            return;
        }
        this._negatedTargets.set(target, flags);
        const dispose = ide_utils_1.Disposable.create(() => {
            this.unNegateTarget(target);
        });
        this.negatedTargetsDisposables.set(target, dispose);
        this.onDidNegateTargetEmitter.fire({ decoration: this, target });
        return dispose;
    }
    /**
     * 取消否定装饰器绑定
     * @param target
     */
    unNegateTarget(target) {
        if (this._negatedTargets.delete(target)) {
            const disposable = this.negatedTargetsDisposables.get(target);
            if (disposable) {
                disposable.dispose();
            }
            this.onDidUnNegateTargetEmitter.fire({ decoration: this, target });
        }
    }
}
exports.Decoration = Decoration;
//# sourceMappingURL=Decoration.js.map