/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/


/**
 * AUTO-GENERATED FILE. DO NOT MODIFY.
 */

/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements.  See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership.  The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License.  You may obtain a copy of the License at
*
*   http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied.  See the License for the
* specific language governing permissions and limitations
* under the License.
*/
import { __extends } from "tslib"; // TODO Batch by color

import * as graphic from '../../util/graphic.js';
import * as lineContain from 'zrender/lib/contain/line.js';
import * as quadraticContain from 'zrender/lib/contain/quadratic.js';
import { getECData } from '../../util/innerStore.js';

var LargeLinesPathShape =
/** @class */
function () {
  function LargeLinesPathShape() {
    this.polyline = false;
    this.curveness = 0;
    this.segs = [];
  }

  return LargeLinesPathShape;
}();

var LargeLinesPath =
/** @class */
function (_super) {
  __extends(LargeLinesPath, _super);

  function LargeLinesPath(opts) {
    var _this = _super.call(this, opts) || this;

    _this._off = 0;
    _this.hoverDataIdx = -1;
    return _this;
  }

  LargeLinesPath.prototype.reset = function () {
    this.notClear = false;
    this._off = 0;
  };

  LargeLinesPath.prototype.getDefaultStyle = function () {
    return {
      stroke: '#000',
      fill: null
    };
  };

  LargeLinesPath.prototype.getDefaultShape = function () {
    return new LargeLinesPathShape();
  };

  LargeLinesPath.prototype.buildPath = function (ctx, shape) {
    var segs = shape.segs;
    var curveness = shape.curveness;
    var i;

    if (shape.polyline) {
      for (i = this._off; i < segs.length;) {
        var count = segs[i++];

        if (count > 0) {
          ctx.moveTo(segs[i++], segs[i++]);

          for (var k = 1; k < count; k++) {
            ctx.lineTo(segs[i++], segs[i++]);
          }
        }
      }
    } else {
      for (i = this._off; i < segs.length;) {
        var x0 = segs[i++];
        var y0 = segs[i++];
        var x1 = segs[i++];
        var y1 = segs[i++];
        ctx.moveTo(x0, y0);

        if (curveness > 0) {
          var x2 = (x0 + x1) / 2 - (y0 - y1) * curveness;
          var y2 = (y0 + y1) / 2 - (x1 - x0) * curveness;
          ctx.quadraticCurveTo(x2, y2, x1, y1);
        } else {
          ctx.lineTo(x1, y1);
        }
      }
    }

    if (this.incremental) {
      this._off = i;
      this.notClear = true;
    }
  };

  LargeLinesPath.prototype.findDataIndex = function (x, y) {
    var shape = this.shape;
    var segs = shape.segs;
    var curveness = shape.curveness;
    var lineWidth = this.style.lineWidth;

    if (shape.polyline) {
      var dataIndex = 0;

      for (var i = 0; i < segs.length;) {
        var count = segs[i++];

        if (count > 0) {
          var x0 = segs[i++];
          var y0 = segs[i++];

          for (var k = 1; k < count; k++) {
            var x1 = segs[i++];
            var y1 = segs[i++];

            if (lineContain.containStroke(x0, y0, x1, y1, lineWidth, x, y)) {
              return dataIndex;
            }
          }
        }

        dataIndex++;
      }
    } else {
      var dataIndex = 0;

      for (var i = 0; i < segs.length;) {
        var x0 = segs[i++];
        var y0 = segs[i++];
        var x1 = segs[i++];
        var y1 = segs[i++];

        if (curveness > 0) {
          var x2 = (x0 + x1) / 2 - (y0 - y1) * curveness;
          var y2 = (y0 + y1) / 2 - (x1 - x0) * curveness;

          if (quadraticContain.containStroke(x0, y0, x2, y2, x1, y1, lineWidth, x, y)) {
            return dataIndex;
          }
        } else {
          if (lineContain.containStroke(x0, y0, x1, y1, lineWidth, x, y)) {
            return dataIndex;
          }
        }

        dataIndex++;
      }
    }

    return -1;
  };

  LargeLinesPath.prototype.contain = function (x, y) {
    var localPos = this.transformCoordToLocal(x, y);
    var rect = this.getBoundingRect();
    x = localPos[0];
    y = localPos[1];

    if (rect.contain(x, y)) {
      // Cache found data index.
      var dataIdx = this.hoverDataIdx = this.findDataIndex(x, y);
      return dataIdx >= 0;
    }

    this.hoverDataIdx = -1;
    return false;
  };

  LargeLinesPath.prototype.getBoundingRect = function () {
    // Ignore stroke for large symbol draw.
    var rect = this._rect;

    if (!rect) {
      var shape = this.shape;
      var points = shape.segs;
      var minX = Infinity;
      var minY = Infinity;
      var maxX = -Infinity;
      var maxY = -Infinity;

      for (var i = 0; i < points.length;) {
        var x = points[i++];
        var y = points[i++];
        minX = Math.min(x, minX);
        maxX = Math.max(x, maxX);
        minY = Math.min(y, minY);
        maxY = Math.max(y, maxY);
      }

      rect = this._rect = new graphic.BoundingRect(minX, minY, maxX, maxY);
    }

    return rect;
  };

  return LargeLinesPath;
}(graphic.Path);

var LargeLineDraw =
/** @class */
function () {
  function LargeLineDraw() {
    this.group = new graphic.Group();
  }
  /**
   * Update symbols draw by new data
   */


  LargeLineDraw.prototype.updateData = function (data) {
    this._clear();

    var lineEl = this._create();

    lineEl.setShape({
      segs: data.getLayout('linesPoints')
    });

    this._setCommon(lineEl, data);
  };

  ;
  /**
   * @override
   */

  LargeLineDraw.prototype.incrementalPrepareUpdate = function (data) {
    this.group.removeAll();

    this._clear();
  };

  ;
  /**
   * @override
   */

  LargeLineDraw.prototype.incrementalUpdate = function (taskParams, data) {
    var lastAdded = this._newAdded[0];
    var linePoints = data.getLayout('linesPoints');
    var oldSegs = lastAdded && lastAdded.shape.segs; // Merging the exists. Each element has 1e4 points.
    // Consider the performance balance between too much elements and too much points in one shape(may affect hover optimization)

    if (oldSegs && oldSegs.length < 2e4) {
      var oldLen = oldSegs.length;
      var newSegs = new Float32Array(oldLen + linePoints.length); // Concat two array

      newSegs.set(oldSegs);
      newSegs.set(linePoints, oldLen);
      lastAdded.setShape({
        segs: newSegs
      });
    } else {
      // Clear
      this._newAdded = [];

      var lineEl = this._create();

      lineEl.incremental = true;
      lineEl.setShape({
        segs: linePoints
      });

      this._setCommon(lineEl, data);

      lineEl.__startIndex = taskParams.start;
    }
  };
  /**
   * @override
   */


  LargeLineDraw.prototype.remove = function () {
    this._clear();
  };

  LargeLineDraw.prototype.eachRendered = function (cb) {
    this._newAdded[0] && cb(this._newAdded[0]);
  };

  LargeLineDraw.prototype._create = function () {
    var lineEl = new LargeLinesPath({
      cursor: 'default',
      ignoreCoarsePointer: true
    });

    this._newAdded.push(lineEl);

    this.group.add(lineEl);
    return lineEl;
  };

  LargeLineDraw.prototype._setCommon = function (lineEl, data, isIncremental) {
    var hostModel = data.hostModel;
    lineEl.setShape({
      polyline: hostModel.get('polyline'),
      curveness: hostModel.get(['lineStyle', 'curveness'])
    });
    lineEl.useStyle(hostModel.getModel('lineStyle').getLineStyle());
    lineEl.style.strokeNoScale = true;
    var style = data.getVisual('style');

    if (style && style.stroke) {
      lineEl.setStyle('stroke', style.stroke);
    }

    lineEl.setStyle('fill', null);
    var ecData = getECData(lineEl); // Enable tooltip
    // PENDING May have performance issue when path is extremely large

    ecData.seriesIndex = hostModel.seriesIndex;
    lineEl.on('mousemove', function (e) {
      ecData.dataIndex = null;
      var dataIndex = lineEl.hoverDataIdx;

      if (dataIndex > 0) {
        // Provide dataIndex for tooltip
        ecData.dataIndex = dataIndex + lineEl.__startIndex;
      }
    });
  };

  ;

  LargeLineDraw.prototype._clear = function () {
    this._newAdded = [];
    this.group.removeAll();
  };

  ;
  return LargeLineDraw;
}();

export default LargeLineDraw;