import * as echarts from 'echarts/lib/echarts';
import graphicGL from '../../util/graphicGL';
import LinesGeometry from '../../util/geometry/Lines3D'; // import TrailMesh from './TrailMesh';

import TrailMesh2 from './TrailMesh2';
import { getItemVisualColor, getItemVisualOpacity } from '../../util/visual';
import lines3DGLSL from '../../util/shader/lines3D.glsl.js';
graphicGL.Shader.import(lines3DGLSL);

function getCoordSysSize(coordSys) {
  if (coordSys.radius != null) {
    return coordSys.radius;
  }

  if (coordSys.size != null) {
    return Math.max(coordSys.size[0], coordSys.size[1], coordSys.size[2]);
  } else {
    return 100;
  }
}

export default echarts.ChartView.extend({
  type: 'lines3D',
  __ecgl__: true,
  init: function (ecModel, api) {
    this.groupGL = new graphicGL.Node();
    this._meshLinesMaterial = new graphicGL.Material({
      shader: graphicGL.createShader('ecgl.meshLines3D'),
      transparent: true,
      depthMask: false
    });
    this._linesMesh = new graphicGL.Mesh({
      geometry: new LinesGeometry(),
      material: this._meshLinesMaterial,
      $ignorePicking: true
    }); // this._trailMesh = new TrailMesh();

    this._trailMesh = new TrailMesh2();
  },
  render: function (seriesModel, ecModel, api) {
    this.groupGL.add(this._linesMesh);
    var coordSys = seriesModel.coordinateSystem;
    var data = seriesModel.getData();

    if (coordSys && coordSys.viewGL) {
      var viewGL = coordSys.viewGL;
      viewGL.add(this.groupGL);

      this._updateLines(seriesModel, ecModel, api);

      var methodName = coordSys.viewGL.isLinearSpace() ? 'define' : 'undefine';

      this._linesMesh.material[methodName]('fragment', 'SRGB_DECODE');

      this._trailMesh.material[methodName]('fragment', 'SRGB_DECODE');
    }

    var trailMesh = this._trailMesh;
    trailMesh.stopAnimation();

    if (seriesModel.get('effect.show')) {
      this.groupGL.add(trailMesh);
      trailMesh.updateData(data, api, this._linesMesh.geometry);
      trailMesh.__time = trailMesh.__time || 0;
      var time = 3600 * 1000; // 1hour

      this._curveEffectsAnimator = trailMesh.animate('', {
        loop: true
      }).when(time, {
        __time: time
      }).during(function () {
        trailMesh.setAnimationTime(trailMesh.__time);
      }).start();
    } else {
      this.groupGL.remove(trailMesh);
      this._curveEffectsAnimator = null;
    }

    this._linesMesh.material.blend = this._trailMesh.material.blend = seriesModel.get('blendMode') === 'lighter' ? graphicGL.additiveBlend : null;
  },
  pauseEffect: function () {
    if (this._curveEffectsAnimator) {
      this._curveEffectsAnimator.pause();
    }
  },
  resumeEffect: function () {
    if (this._curveEffectsAnimator) {
      this._curveEffectsAnimator.resume();
    }
  },
  toggleEffect: function () {
    var animator = this._curveEffectsAnimator;

    if (animator) {
      animator.isPaused() ? animator.resume() : animator.pause();
    }
  },
  _updateLines: function (seriesModel, ecModel, api) {
    var data = seriesModel.getData();
    var coordSys = seriesModel.coordinateSystem;
    var geometry = this._linesMesh.geometry;
    var isPolyline = seriesModel.get('polyline');
    geometry.expandLine = true;
    var size = getCoordSysSize(coordSys);
    geometry.segmentScale = size / 20;
    var lineWidthQueryPath = 'lineStyle.width'.split('.');
    var dpr = api.getDevicePixelRatio();
    var maxLineWidth = 0;
    data.each(function (idx) {
      var itemModel = data.getItemModel(idx);
      var lineWidth = itemModel.get(lineWidthQueryPath);

      if (lineWidth == null) {
        lineWidth = 1;
      }

      data.setItemVisual(idx, 'lineWidth', lineWidth);
      maxLineWidth = Math.max(lineWidth, maxLineWidth);
    }); // Must set useNativeLine before calling any other methods

    geometry.useNativeLine = false;
    var nVertex = 0;
    var nTriangle = 0;
    data.each(function (idx) {
      var pts = data.getItemLayout(idx);

      if (isPolyline) {
        nVertex += geometry.getPolylineVertexCount(pts);
        nTriangle += geometry.getPolylineTriangleCount(pts);
      } else {
        nVertex += geometry.getCubicCurveVertexCount(pts[0], pts[1], pts[2], pts[3]);
        nTriangle += geometry.getCubicCurveTriangleCount(pts[0], pts[1], pts[2], pts[3]);
      }
    });
    geometry.setVertexCount(nVertex);
    geometry.setTriangleCount(nTriangle);
    geometry.resetOffset();
    var colorArr = [];
    data.each(function (idx) {
      var pts = data.getItemLayout(idx);
      var color = getItemVisualColor(data, idx);
      var opacity = getItemVisualOpacity(data, idx);
      var lineWidth = data.getItemVisual(idx, 'lineWidth') * dpr;

      if (opacity == null) {
        opacity = 1;
      }

      colorArr = graphicGL.parseColor(color, colorArr);
      colorArr[3] *= opacity;

      if (isPolyline) {
        geometry.addPolyline(pts, colorArr, lineWidth);
      } else {
        geometry.addCubicCurve(pts[0], pts[1], pts[2], pts[3], colorArr, lineWidth);
      }
    });
    geometry.dirty();
  },
  remove: function () {
    this.groupGL.removeAll();
  },
  dispose: function () {
    this.groupGL.removeAll();
  }
});