import * as echarts from 'echarts/lib/echarts';
import componentShadingMixin from '../../component/common/componentShadingMixin';
import formatTooltip from '../common/formatTooltip';
import createList from '../common/createList';
var SurfaceSeries = echarts.SeriesModel.extend({
  type: 'series.surface',
  dependencies: ['globe', 'grid3D', 'geo3D'],
  visualStyleAccessPath: 'itemStyle',
  formatTooltip: function (dataIndex) {
    return formatTooltip(this, dataIndex);
  },
  getInitialData: function (option, ecModel) {
    var data = option.data;

    function validateDimension(dimOpts) {
      return !(isNaN(dimOpts.min) || isNaN(dimOpts.max) || isNaN(dimOpts.step));
    }

    function getPrecision(dimOpts) {
      var getPrecision = echarts.number.getPrecisionSafe;
      return Math.max(getPrecision(dimOpts.min), getPrecision(dimOpts.max), getPrecision(dimOpts.step)) + 1;
    }

    if (!data) {
      if (!option.parametric) {
        // From surface equation
        var equation = option.equation || {};
        var xOpts = equation.x || {};
        var yOpts = equation.y || {};
        ['x', 'y'].forEach(function (dim) {
          if (!validateDimension(equation[dim])) {
            if (process.env.NODE_ENV !== 'production') {
              console.error('Invalid equation.%s', dim);
            }

            return;
          }
        });

        if (typeof equation.z !== 'function') {
          if (process.env.NODE_ENV !== 'production') {
            console.error('equation.z needs to be function');
          }

          return;
        }

        var xCount = Math.floor((xOpts.max + xOpts.step - xOpts.min) / xOpts.step);
        var yCount = Math.floor((yOpts.max + yOpts.step - yOpts.min) / yOpts.step);
        data = new Float32Array(xCount * yCount * 3);
        var xPrecision = getPrecision(xOpts);
        var yPrecision = getPrecision(yOpts);
        var off = 0;

        for (var j = 0; j < yCount; j++) {
          for (var i = 0; i < xCount; i++) {
            var x = i * xOpts.step + xOpts.min;
            var y = j * yOpts.step + yOpts.min;
            var x2 = echarts.number.round(Math.min(x, xOpts.max), xPrecision);
            var y2 = echarts.number.round(Math.min(y, yOpts.max), yPrecision);
            var z = equation.z(x2, y2);
            data[off++] = x2;
            data[off++] = y2;
            data[off++] = z;
          }
        }
      } else {
        var parametricEquation = option.parametricEquation || {};
        var uOpts = parametricEquation.u || {};
        var vOpts = parametricEquation.v || {};
        ['u', 'v'].forEach(function (dim) {
          if (!validateDimension(parametricEquation[dim])) {
            if (process.env.NODE_ENV !== 'production') {
              console.error('Invalid parametricEquation.%s', dim);
            }

            return;
          }
        });
        ['x', 'y', 'z'].forEach(function (dim) {
          if (typeof parametricEquation[dim] !== 'function') {
            if (process.env.NODE_ENV !== 'production') {
              console.error('parametricEquation.%s needs to be function', dim);
            }

            return;
          }
        });
        var uCount = Math.floor((uOpts.max + uOpts.step - uOpts.min) / uOpts.step);
        var vCount = Math.floor((vOpts.max + vOpts.step - vOpts.min) / vOpts.step);
        data = new Float32Array(uCount * vCount * 5);
        var uPrecision = getPrecision(uOpts);
        var vPrecision = getPrecision(vOpts);
        var off = 0;

        for (var j = 0; j < vCount; j++) {
          for (var i = 0; i < uCount; i++) {
            var u = i * uOpts.step + uOpts.min;
            var v = j * vOpts.step + vOpts.min;
            var u2 = echarts.number.round(Math.min(u, uOpts.max), uPrecision);
            var v2 = echarts.number.round(Math.min(v, vOpts.max), vPrecision);
            var x = parametricEquation.x(u2, v2);
            var y = parametricEquation.y(u2, v2);
            var z = parametricEquation.z(u2, v2);
            data[off++] = x;
            data[off++] = y;
            data[off++] = z;
            data[off++] = u2;
            data[off++] = v2;
          }
        }
      }
    }

    var dims = ['x', 'y', 'z'];

    if (option.parametric) {
      dims.push('u', 'v');
    } // PENDING getSource?


    var list = createList(this, dims, data);
    return list;
  },
  defaultOption: {
    coordinateSystem: 'cartesian3D',
    zlevel: -10,
    // Cartesian coordinate system
    grid3DIndex: 0,
    // Surface needs lambert shading to show the difference
    shading: 'lambert',
    // If parametric surface
    parametric: false,
    wireframe: {
      show: true,
      lineStyle: {
        color: 'rgba(0,0,0,0.5)',
        width: 1
      }
    },

    /**
     * Generate surface data from z = f(x, y) equation
     */
    equation: {
      // [min, max, step]
      x: {
        min: -1,
        max: 1,
        step: 0.1
      },
      y: {
        min: -1,
        max: 1,
        step: 0.1
      },
      z: null
    },
    parametricEquation: {
      // [min, max, step]
      u: {
        min: -1,
        max: 1,
        step: 0.1
      },
      v: {
        min: -1,
        max: 1,
        step: 0.1
      },
      // [x, y, z] = f(x, y)
      x: null,
      y: null,
      z: null
    },
    // Shape of give data
    // It is an array to specify rows and columns.
    // For example [30, 30]
    dataShape: null,
    itemStyle: {// Color
    },
    animationDurationUpdate: 500
  }
});
echarts.util.merge(SurfaceSeries.prototype, componentShadingMixin);
export default SurfaceSeries;