import graphicGL from '../../util/graphicGL';
import verticesSortMixin from '../../util/geometry/verticesSortMixin';
import * as echarts from 'echarts/lib/echarts';
import glmatrix from 'claygl/src/dep/glmatrix';
var vec4 = glmatrix.vec4;
import sdfSpriteGLSL from './sdfSprite.glsl.js';
graphicGL.Shader.import(sdfSpriteGLSL);
var PointsMesh = graphicGL.Mesh.extend(function () {
  var geometry = new graphicGL.Geometry({
    dynamic: true,
    attributes: {
      color: new graphicGL.Geometry.Attribute('color', 'float', 4, 'COLOR'),
      position: new graphicGL.Geometry.Attribute('position', 'float', 3, 'POSITION'),
      size: new graphicGL.Geometry.Attribute('size', 'float', 1),
      prevPosition: new graphicGL.Geometry.Attribute('prevPosition', 'float', 3),
      prevSize: new graphicGL.Geometry.Attribute('prevSize', 'float', 1)
    }
  });
  Object.assign(geometry, verticesSortMixin);
  var material = new graphicGL.Material({
    shader: graphicGL.createShader('ecgl.sdfSprite'),
    transparent: true,
    depthMask: false
  });
  material.enableTexture('sprite');
  material.define('both', 'VERTEX_COLOR');
  material.define('both', 'VERTEX_SIZE');
  var sdfTexture = new graphicGL.Texture2D({
    image: document.createElement('canvas'),
    flipY: false
  });
  material.set('sprite', sdfTexture); // Custom pick methods.

  geometry.pick = this._pick.bind(this);
  return {
    geometry: geometry,
    material: material,
    mode: graphicGL.Mesh.POINTS,
    sizeScale: 1
  };
}, {
  _pick: function (x, y, renderer, camera, renderable, out) {
    var positionNDC = this._positionNDC;

    if (!positionNDC) {
      return;
    }

    var viewport = renderer.viewport;
    var ndcScaleX = 2 / viewport.width;
    var ndcScaleY = 2 / viewport.height; // From near to far. indices have been sorted.

    for (var i = this.geometry.vertexCount - 1; i >= 0; i--) {
      var idx;

      if (!this.geometry.indices) {
        idx = i;
      } else {
        idx = this.geometry.indices[i];
      }

      var cx = positionNDC[idx * 2];
      var cy = positionNDC[idx * 2 + 1];
      var size = this.geometry.attributes.size.get(idx) / this.sizeScale;
      var halfSize = size / 2;

      if (x > cx - halfSize * ndcScaleX && x < cx + halfSize * ndcScaleX && y > cy - halfSize * ndcScaleY && y < cy + halfSize * ndcScaleY) {
        var point = new graphicGL.Vector3();
        var pointWorld = new graphicGL.Vector3();
        this.geometry.attributes.position.get(idx, point.array);
        graphicGL.Vector3.transformMat4(pointWorld, point, this.worldTransform);
        out.push({
          vertexIndex: idx,
          point: point,
          pointWorld: pointWorld,
          target: this,
          distance: pointWorld.distance(camera.getWorldPosition())
        });
      }
    }
  },
  updateNDCPosition: function (worldViewProjection, is2D, api) {
    var positionNDC = this._positionNDC;
    var geometry = this.geometry;

    if (!positionNDC || positionNDC.length / 2 !== geometry.vertexCount) {
      positionNDC = this._positionNDC = new Float32Array(geometry.vertexCount * 2);
    }

    var pos = vec4.create();

    for (var i = 0; i < geometry.vertexCount; i++) {
      geometry.attributes.position.get(i, pos);
      pos[3] = 1;
      vec4.transformMat4(pos, pos, worldViewProjection.array);
      vec4.scale(pos, pos, 1 / pos[3]);
      positionNDC[i * 2] = pos[0];
      positionNDC[i * 2 + 1] = pos[1];
    }
  }
});
export default PointsMesh;