import { deepEqual } from '../utils/deep-equal';
import LightingEffect from '../effects/lighting/lighting-effect';
const DEFAULT_LIGHTING_EFFECT = new LightingEffect();

function compareEffects(e1, e2) {
  var _e1$order, _e2$order;

  const o1 = (_e1$order = e1.order) !== null && _e1$order !== void 0 ? _e1$order : Infinity;
  const o2 = (_e2$order = e2.order) !== null && _e2$order !== void 0 ? _e2$order : Infinity;
  return o1 - o2;
}

export default class EffectManager {
  constructor() {
    this.effects = void 0;
    this._resolvedEffects = [];
    this._defaultEffects = [];
    this._needsRedraw = void 0;
    this.effects = [];
    this._needsRedraw = 'Initial render';

    this._setEffects([]);
  }

  addDefaultEffect(effect) {
    const defaultEffects = this._defaultEffects;

    if (!defaultEffects.find(e => e.id === effect.id)) {
      const index = defaultEffects.findIndex(e => compareEffects(e, effect) > 0);

      if (index < 0) {
        defaultEffects.push(effect);
      } else {
        defaultEffects.splice(index, 0, effect);
      }

      this._setEffects(this.effects);
    }
  }

  setProps(props) {
    if ('effects' in props) {
      if (!deepEqual(props.effects, this.effects, 1)) {
        this._setEffects(props.effects);
      }
    }
  }

  needsRedraw(opts = {
    clearRedrawFlags: false
  }) {
    const redraw = this._needsRedraw;

    if (opts.clearRedrawFlags) {
      this._needsRedraw = false;
    }

    return redraw;
  }

  getEffects() {
    return this._resolvedEffects;
  }

  _setEffects(effects) {
    const oldEffectsMap = {};

    for (const effect of this.effects) {
      oldEffectsMap[effect.id] = effect;
    }

    const nextEffects = [];

    for (const effect of effects) {
      const oldEffect = oldEffectsMap[effect.id];

      if (oldEffect && oldEffect !== effect) {
        if (oldEffect.setProps) {
          oldEffect.setProps(effect.props);
          nextEffects.push(oldEffect);
        } else {
          oldEffect.cleanup();
          nextEffects.push(effect);
        }
      } else {
        nextEffects.push(effect);
      }

      delete oldEffectsMap[effect.id];
    }

    for (const removedEffectId in oldEffectsMap) {
      oldEffectsMap[removedEffectId].cleanup();
    }

    this.effects = nextEffects;
    this._resolvedEffects = nextEffects.concat(this._defaultEffects);

    if (!effects.some(effect => effect instanceof LightingEffect)) {
      this._resolvedEffects.push(DEFAULT_LIGHTING_EFFECT);
    }

    this._needsRedraw = 'effects changed';
  }

  finalize() {
    for (const effect of this._resolvedEffects) {
      effect.cleanup();
    }

    this.effects.length = 0;
    this._resolvedEffects.length = 0;
    this._defaultEffects.length = 0;
  }

}
//# sourceMappingURL=effect-manager.js.map