"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.Effect = void 0;
exports.effect = effect;
const system_js_1 = require("./system.js");
function effect(fn) {
    const e = new Effect(fn);
    e.run();
    return e;
}
class Effect {
    constructor(fn) {
        this.fn = fn;
        this.nextNotify = undefined;
        // Dependency
        this.subs = undefined;
        this.subsTail = undefined;
        this.linkedTrackId = -1;
        // Subscriber
        this.deps = undefined;
        this.depsTail = undefined;
        this.trackId = 0;
        this.dirtyLevel = 3 /* DirtyLevels.Dirty */;
        this.canPropagate = false;
        const subVersion = system_js_1.System.activeTrackId;
        if (subVersion !== 0 && this.linkedTrackId !== subVersion) {
            this.linkedTrackId = subVersion;
            system_js_1.Dependency.linkSubscriber(this, system_js_1.System.activeSub);
            return;
        }
        const activeTrackId = system_js_1.System.activeEffectScopeTrackId;
        if (activeTrackId !== 0 && this.linkedTrackId !== activeTrackId) {
            this.linkedTrackId = activeTrackId;
            system_js_1.Dependency.linkSubscriber(this, system_js_1.System.activeEffectScope);
        }
    }
    notify() {
        const dirtyLevel = this.dirtyLevel;
        if (dirtyLevel === 1 /* DirtyLevels.SideEffectsOnly */) {
            this.dirtyLevel = 0 /* DirtyLevels.None */;
            system_js_1.Subscriber.runInnerEffects(this.deps);
        }
        else {
            if (dirtyLevel === 2 /* DirtyLevels.MaybeDirty */) {
                system_js_1.Subscriber.resolveMaybeDirty(this);
            }
            if (this.dirtyLevel === 3 /* DirtyLevels.Dirty */) {
                this.run();
            }
            else {
                system_js_1.Subscriber.runInnerEffects(this.deps);
            }
        }
    }
    run() {
        const prevSub = system_js_1.Subscriber.startTrackDependencies(this);
        try {
            this.fn();
        }
        finally {
            system_js_1.Subscriber.endTrackDependencies(this, prevSub);
        }
    }
    stop() {
        if (this.deps !== undefined) {
            system_js_1.Subscriber.clearTrack(this.deps);
            this.deps = undefined;
            this.depsTail = undefined;
        }
        this.dirtyLevel = 3 /* DirtyLevels.Dirty */;
    }
}
exports.Effect = Effect;
