import { StyleEvaluator } from "./styles/evaluators.js";
import { parseExpressions } from "./styles/parsers.js";
import { StyleEffector } from "./styles/style-effector.js";
/* @license
 * Copyright 2019 Google LLC. All Rights Reserved.
 * Licensed under the Apache License, Version 2.0 (the 'License');
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an 'AS IS' BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
const style = (config) => {
  const observeEffects = config.observeEffects || false;
  const getIntrinsics = config.intrinsics instanceof Function ? config.intrinsics : () => config.intrinsics;
  return (proto, propertyName) => {
    const originalUpdated = proto.updated;
    const originalConnectedCallback = proto.connectedCallback;
    const originalDisconnectedCallback = proto.disconnectedCallback;
    const $styleEffector = Symbol(`${propertyName}StyleEffector`);
    const $styleEvaluator = Symbol(`${propertyName}StyleEvaluator`);
    const $updateEvaluator = Symbol(`${propertyName}UpdateEvaluator`);
    const $evaluateAndSync = Symbol(`${propertyName}EvaluateAndSync`);
    Object.defineProperties(proto, {
      [$styleEffector]: { value: null, writable: true },
      [$styleEvaluator]: { value: null, writable: true },
      [$updateEvaluator]: {
        value: function() {
          const ast = parseExpressions(this[propertyName]);
          this[$styleEvaluator] = new StyleEvaluator(ast, getIntrinsics(this));
          if (this[$styleEffector] == null && observeEffects) {
            this[$styleEffector] = new StyleEffector(() => this[$evaluateAndSync]());
          }
          if (this[$styleEffector] != null) {
            this[$styleEffector].observeEffectsFor(ast);
          }
        }
      },
      [$evaluateAndSync]: {
        value: function() {
          if (this[$styleEvaluator] == null) {
            return;
          }
          const result = this[$styleEvaluator].evaluate();
          this[config.updateHandler](result);
        }
      },
      updated: {
        value: function(changedProperties) {
          if (changedProperties.has(propertyName)) {
            this[$updateEvaluator]();
            this[$evaluateAndSync]();
          }
          originalUpdated.call(this, changedProperties);
        }
      },
      connectedCallback: {
        value: function() {
          originalConnectedCallback.call(this);
          this.requestUpdate(propertyName, this[propertyName]);
        }
      },
      disconnectedCallback: {
        value: function() {
          originalDisconnectedCallback.call(this);
          if (this[$styleEffector] != null) {
            this[$styleEffector].dispose();
            this[$styleEffector] = null;
          }
        }
      }
    });
  };
};
export {
  style
};
//# sourceMappingURL=decorators.js.map
