import LayersPass from './layers-pass';
import { withGLParameters } from '@luma.gl/webgl';
import { GL } from '@luma.gl/constants';
import log from '../utils/log';
const PICKING_PARAMETERS = {
  blendFunc: [1, 0, 32771, 0],
  blendEquation: 32774
};
export default class PickLayersPass extends LayersPass {
  constructor(...args) {
    super(...args);
    this.pickZ = void 0;
    this._colorEncoderState = null;
  }

  render(props) {
    if ('pickingFBO' in props) {
      return this._drawPickingBuffer(props);
    }

    return super.render(props);
  }

  _drawPickingBuffer({
    layers,
    layerFilter,
    views,
    viewports,
    onViewportActive,
    pickingFBO,
    deviceRect: {
      x,
      y,
      width,
      height
    },
    cullRect,
    effects,
    pass = 'picking',
    pickZ,
    moduleParameters
  }) {
    this.pickZ = pickZ;

    const colorEncoderState = this._resetColorEncoder(pickZ);

    const renderStatus = withGLParameters(this.device, {
      scissorTest: true,
      scissor: [x, y, width, height],
      clearColor: [0, 0, 0, 0],
      depthMask: true,
      depthTest: true,
      depthRange: [0, 1],
      colorMask: [true, true, true, true],
      ...PICKING_PARAMETERS,
      blend: !pickZ
    }, () => super.render({
      target: pickingFBO,
      layers,
      layerFilter,
      views,
      viewports,
      onViewportActive,
      cullRect,
      effects: effects === null || effects === void 0 ? void 0 : effects.filter(e => e.useInPicking),
      pass,
      isPicking: true,
      moduleParameters
    }));
    this._colorEncoderState = null;
    const decodePickingColor = colorEncoderState && decodeColor.bind(null, colorEncoderState);
    return {
      decodePickingColor,
      stats: renderStatus
    };
  }

  shouldDrawLayer(layer) {
    const {
      pickable,
      operation
    } = layer.props;
    return pickable && operation.includes('draw') || operation.includes('terrain') || operation.includes('mask');
  }

  getModuleParameters() {
    return {
      picking: {
        isActive: 1,
        isAttribute: this.pickZ
      },
      lightSources: {}
    };
  }

  getLayerParameters(layer, layerIndex, viewport) {
    const pickParameters = { ...layer.props.parameters
    };
    const {
      pickable,
      operation
    } = layer.props;

    if (!this._colorEncoderState) {
      pickParameters.blend = false;
    } else if (pickable && operation.includes('draw')) {
      Object.assign(pickParameters, PICKING_PARAMETERS);
      pickParameters.blend = true;
      pickParameters.blendColor = encodeColor(this._colorEncoderState, layer, viewport);
    }

    if (operation.includes('terrain')) {
      pickParameters.blend = false;
    }

    return pickParameters;
  }

  _resetColorEncoder(pickZ) {
    this._colorEncoderState = pickZ ? null : {
      byLayer: new Map(),
      byAlpha: []
    };
    return this._colorEncoderState;
  }

}

function encodeColor(encoded, layer, viewport) {
  const {
    byLayer,
    byAlpha
  } = encoded;
  let a;
  let entry = byLayer.get(layer);

  if (entry) {
    entry.viewports.push(viewport);
    a = entry.a;
  } else {
    a = byLayer.size + 1;

    if (a <= 255) {
      entry = {
        a,
        layer,
        viewports: [viewport]
      };
      byLayer.set(layer, entry);
      byAlpha[a] = entry;
    } else {
      log.warn('Too many pickable layers, only picking the first 255')();
      a = 0;
    }
  }

  return [0, 0, 0, a / 255];
}

function decodeColor(encoded, pickedColor) {
  const entry = encoded.byAlpha[pickedColor[3]];
  return entry && {
    pickedLayer: entry.layer,
    pickedViewports: entry.viewports,
    pickedObjectIndex: entry.layer.decodePickingColor(pickedColor)
  };
}
//# sourceMappingURL=pick-layers-pass.js.map