System.register(['active-expression', './active-expression-ticking.js', 'utils'], function (_export, _context) {
  "use strict";

  var BaseActiveExpression, check, setExpressionOptionsForConventionStrategies, PausableLoop;
  return {
    setters: [function (_activeExpression) {
      BaseActiveExpression = _activeExpression.BaseActiveExpression;
    }, function (_activeExpressionTickingJs) {
      check = _activeExpressionTickingJs.check;
      setExpressionOptionsForConventionStrategies = _activeExpressionTickingJs.setExpressionOptionsForConventionStrategies;
    }, function (_utils) {
      PausableLoop = _utils.PausableLoop;
    }],
    execute: function () {
      const __SystemJSRewritingHack = {};
      _recorder_._src_client_reactive_active_expression_convention_active_expression_frame_based_js = _recorder_._src_client_reactive_active_expression_convention_active_expression_frame_based_js || {};
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_convention_active_expression_frame_based_js, '__unload__', {
        get() {
          return __unload__;
        },

        set(thisIsVererySecretVariableName) {
          _export('__unload__', __unload__ = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_convention_active_expression_frame_based_js, 'aexpr', {
        get() {
          return aexpr;
        },

        set(thisIsVererySecretVariableName) {
          _export('aexpr', aexpr = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_convention_active_expression_frame_based_js, 'BaseActiveExpression', {
        get() {
          return BaseActiveExpression;
        },

        set(thisIsVererySecretVariableName) {
          BaseActiveExpression = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_convention_active_expression_frame_based_js, 'setExpressionOptionsForConventionStrategies', {
        get() {
          return setExpressionOptionsForConventionStrategies;
        },

        set(thisIsVererySecretVariableName) {
          setExpressionOptionsForConventionStrategies = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_convention_active_expression_frame_based_js, 'check', {
        get() {
          return check;
        },

        set(thisIsVererySecretVariableName) {
          check = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_convention_active_expression_frame_based_js, 'PausableLoop', {
        get() {
          return PausableLoop;
        },

        set(thisIsVererySecretVariableName) {
          PausableLoop = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      class FrameBasedActiveExpression extends BaseActiveExpression {
        constructor(func, ...args) {
          super(func, ...args);
          this.meta({ strategy: 'Frame-based' });

          // needed for check function for aexpr-ticking
          this.enabled = true;

          if (new.target === FrameBasedActiveExpression) {
            this.addToRegistry();
          }
        }

        onChange(...args) {
          const result = super.onChange(...args);

          if (!this._isDisposed) {
            FRAME_BASED_AEXPRS.add(this);
            checkLoop.ensureRunning();
          }

          return result;
        }

        offChange(...args) {
          const result = super.offChange(...args);

          if (!this.hasCallbacks()) {
            this.revoke();
          }

          return result;
        }

        dispose(...args) {
          const result = super.dispose(...args);
          this.revoke();

          return result;
        }

        // #TODO: unused!
        revoke() {
          FRAME_BASED_AEXPRS.delete(this);
          if (FRAME_BASED_AEXPRS.size === 0) {
            checkLoop.pause();
          }
        }

        /** the parameter `checkImmediately` is by default false for convention strategies */
        setExpression(...params) {
          return super.setExpression(...setExpressionOptionsForConventionStrategies(...params));
        }

      }

      _export('FrameBasedActiveExpression', FrameBasedActiveExpression);

      Object.defineProperty(_recorder_._src_client_reactive_active_expression_convention_active_expression_frame_based_js, 'FrameBasedActiveExpression', {
        get() {
          return FrameBasedActiveExpression;
        },

        set(thisIsVererySecretVariableName) {
          _export('FrameBasedActiveExpression', FrameBasedActiveExpression = thisIsVererySecretVariableName);

          return true;
        },

        enumerable: true,
        configurable: true
      });
      function aexpr(func, ...args) {
        return new FrameBasedActiveExpression(func, ...args);
      }

      _export('aexpr', aexpr);

      const FRAME_BASED_AEXPRS = new Set();

      // update Active Expressions once per frame
      Object.defineProperty(_recorder_._src_client_reactive_active_expression_convention_active_expression_frame_based_js, 'FRAME_BASED_AEXPRS', {
        get() {
          return FRAME_BASED_AEXPRS;
        },

        set(thisIsVererySecretVariableName) {
          FRAME_BASED_AEXPRS = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      const checkLoop = new PausableLoop(() => check(FRAME_BASED_AEXPRS));

      Object.defineProperty(_recorder_._src_client_reactive_active_expression_convention_active_expression_frame_based_js, 'checkLoop', {
        get() {
          return checkLoop;
        },

        set(thisIsVererySecretVariableName) {
          checkLoop = thisIsVererySecretVariableName;
          return true;
        },

        enumerable: true,
        configurable: true
      });
      function __unload__() {
        checkLoop.pause();
      }

      _export('__unload__', __unload__);
    }
  };
});