import debug from '../debug';
import DrawLayersPass from '../passes/draw-layers-pass';
import PickLayersPass from '../passes/pick-layers-pass';
const TRACE_RENDER_LAYERS = 'deckRenderer.renderLayers';
export default class DeckRenderer {
  constructor(device) {
    this.device = void 0;
    this.gl = void 0;
    this.layerFilter = void 0;
    this.drawPickingColors = void 0;
    this.drawLayersPass = void 0;
    this.pickLayersPass = void 0;
    this.renderCount = void 0;
    this._needsRedraw = void 0;
    this.renderBuffers = void 0;
    this.lastPostProcessEffect = void 0;
    this.device = device;
    this.gl = device.gl;
    this.layerFilter = null;
    this.drawPickingColors = false;
    this.drawLayersPass = new DrawLayersPass(device);
    this.pickLayersPass = new PickLayersPass(device);
    this.renderCount = 0;
    this._needsRedraw = 'Initial render';
    this.renderBuffers = [];
    this.lastPostProcessEffect = null;
  }

  setProps(props) {
    if (this.layerFilter !== props.layerFilter) {
      this.layerFilter = props.layerFilter;
      this._needsRedraw = 'layerFilter changed';
    }

    if (this.drawPickingColors !== props.drawPickingColors) {
      this.drawPickingColors = props.drawPickingColors;
      this._needsRedraw = 'drawPickingColors changed';
    }
  }

  renderLayers(opts) {
    if (!opts.viewports.length) {
      return;
    }

    const layerPass = this.drawPickingColors ? this.pickLayersPass : this.drawLayersPass;
    const renderOpts = {
      layerFilter: this.layerFilter,
      isPicking: this.drawPickingColors,
      ...opts
    };

    if (renderOpts.effects) {
      this._preRender(renderOpts.effects, renderOpts);
    }

    const outputBuffer = this.lastPostProcessEffect ? this.renderBuffers[0] : renderOpts.target;
    const renderStats = layerPass.render({ ...renderOpts,
      target: outputBuffer
    });

    if (renderOpts.effects) {
      this._postRender(renderOpts.effects, renderOpts);
    }

    this.renderCount++;
    debug(TRACE_RENDER_LAYERS, this, renderStats, opts);
  }

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

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

    return redraw;
  }

  finalize() {
    const {
      renderBuffers
    } = this;

    for (const buffer of renderBuffers) {
      buffer.delete();
    }

    renderBuffers.length = 0;
  }

  _preRender(effects, opts) {
    this.lastPostProcessEffect = null;
    opts.preRenderStats = opts.preRenderStats || {};

    for (const effect of effects) {
      opts.preRenderStats[effect.id] = effect.preRender(this.device, opts);

      if (effect.postRender) {
        this.lastPostProcessEffect = effect.id;
      }
    }

    if (this.lastPostProcessEffect) {
      this._resizeRenderBuffers();
    }
  }

  _resizeRenderBuffers() {
    const {
      renderBuffers
    } = this;

    if (renderBuffers.length === 0) {
      renderBuffers.push(this.device.createFramebuffer({
        colorAttachments: ['rgba8unorm']
      }), this.device.createFramebuffer({
        colorAttachments: ['rgba8unorm']
      }));
    }

    for (const buffer of renderBuffers) {
      buffer.resize();
    }
  }

  _postRender(effects, opts) {
    const {
      renderBuffers
    } = this;
    const params = { ...opts,
      inputBuffer: renderBuffers[0],
      swapBuffer: renderBuffers[1]
    };

    for (const effect of effects) {
      if (effect.postRender) {
        if (effect.id === this.lastPostProcessEffect) {
          params.target = opts.target;
          effect.postRender(this.device, params);
          break;
        }

        const buffer = effect.postRender(this.device, params);
        params.inputBuffer = buffer;
        params.swapBuffer = buffer === renderBuffers[0] ? renderBuffers[1] : renderBuffers[0];
      }
    }
  }

}
//# sourceMappingURL=deck-renderer.js.map