/*
* 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 { __DEV__ } from '../../config';
import * as echarts from '../../echarts';
import * as zrUtil from 'zrender/src/core/util';
import * as graphic from '../../util/graphic';
import { setLabel } from './helper';
import Model from '../../model/Model';
import barItemStyle from './barItemStyle';
import Path from 'zrender/src/graphic/Path';
import { throttle } from '../../util/throttle';
var BAR_BORDER_WIDTH_QUERY = ['itemStyle', 'barBorderWidth'];
var _eventPos = [0, 0]; // FIXME
// Just for compatible with ec2.

zrUtil.extend(Model.prototype, barItemStyle);
export default echarts.extendChartView({
  type: 'bar',
  render: function (seriesModel, ecModel, api) {
    this._updateDrawMode(seriesModel);

    var coordinateSystemType = seriesModel.get('coordinateSystem');

    if (coordinateSystemType === 'cartesian2d' || coordinateSystemType === 'polar') {
      this._isLargeDraw ? this._renderLarge(seriesModel, ecModel, api) : this._renderNormal(seriesModel, ecModel, api);
    } else {}

    return this.group;
  },
  incrementalPrepareRender: function (seriesModel, ecModel, api) {
    this._clear();

    this._updateDrawMode(seriesModel);
  },
  incrementalRender: function (params, seriesModel, ecModel, api) {
    // Do not support progressive in normal mode.
    this._incrementalRenderLarge(params, seriesModel);
  },
  _updateDrawMode: function (seriesModel) {
    var isLargeDraw = seriesModel.pipelineContext.large;

    if (this._isLargeDraw == null || isLargeDraw ^ this._isLargeDraw) {
      this._isLargeDraw = isLargeDraw;

      this._clear();
    }
  },
  _renderNormal: function (seriesModel, ecModel, api) {
    var group = this.group;
    var data = seriesModel.getData();
    var oldData = this._data;
    var coord = seriesModel.coordinateSystem;
    var baseAxis = coord.getBaseAxis();
    var isHorizontalOrRadial;

    if (coord.type === 'cartesian2d') {
      isHorizontalOrRadial = baseAxis.isHorizontal();
    } else if (coord.type === 'polar') {
      isHorizontalOrRadial = baseAxis.dim === 'angle';
    }

    var animationModel = seriesModel.isAnimationEnabled() ? seriesModel : null;
    data.diff(oldData).add(function (dataIndex) {
      if (!data.hasValue(dataIndex)) {
        return;
      }

      var itemModel = data.getItemModel(dataIndex);
      var layout = getLayout[coord.type](data, dataIndex, itemModel);
      var el = elementCreator[coord.type](data, dataIndex, itemModel, layout, isHorizontalOrRadial, animationModel);
      data.setItemGraphicEl(dataIndex, el);
      group.add(el);
      updateStyle(el, data, dataIndex, itemModel, layout, seriesModel, isHorizontalOrRadial, coord.type === 'polar');
    }).update(function (newIndex, oldIndex) {
      var el = oldData.getItemGraphicEl(oldIndex);

      if (!data.hasValue(newIndex)) {
        group.remove(el);
        return;
      }

      var itemModel = data.getItemModel(newIndex);
      var layout = getLayout[coord.type](data, newIndex, itemModel);

      if (el) {
        graphic.updateProps(el, {
          shape: layout
        }, animationModel, newIndex);
      } else {
        el = elementCreator[coord.type](data, newIndex, itemModel, layout, isHorizontalOrRadial, animationModel, true);
      }

      data.setItemGraphicEl(newIndex, el); // Add back

      group.add(el);
      updateStyle(el, data, newIndex, itemModel, layout, seriesModel, isHorizontalOrRadial, coord.type === 'polar');
    }).remove(function (dataIndex) {
      var el = oldData.getItemGraphicEl(dataIndex);

      if (coord.type === 'cartesian2d') {
        el && removeRect(dataIndex, animationModel, el);
      } else {
        el && removeSector(dataIndex, animationModel, el);
      }
    }).execute();
    this._data = data;
  },
  _renderLarge: function (seriesModel, ecModel, api) {
    this._clear();

    createLarge(seriesModel, this.group);
  },
  _incrementalRenderLarge: function (params, seriesModel) {
    createLarge(seriesModel, this.group, true);
  },
  dispose: zrUtil.noop,
  remove: function (ecModel) {
    this._clear(ecModel);
  },
  _clear: function (ecModel) {
    var group = this.group;
    var data = this._data;

    if (ecModel && ecModel.get('animation') && data && !this._isLargeDraw) {
      data.eachItemGraphicEl(function (el) {
        if (el.type === 'sector') {
          removeSector(el.dataIndex, ecModel, el);
        } else {
          removeRect(el.dataIndex, ecModel, el);
        }
      });
    } else {
      group.removeAll();
    }

    this._data = null;
  }
});
var elementCreator = {
  cartesian2d: function (data, dataIndex, itemModel, layout, isHorizontal, animationModel, isUpdate) {
    var rect = new graphic.Rect({
      shape: zrUtil.extend({}, layout)
    }); // Animation

    if (animationModel) {
      var rectShape = rect.shape;
      var animateProperty = isHorizontal ? 'height' : 'width';
      var animateTarget = {};
      rectShape[animateProperty] = 0;
      animateTarget[animateProperty] = layout[animateProperty];
      graphic[isUpdate ? 'updateProps' : 'initProps'](rect, {
        shape: animateTarget
      }, animationModel, dataIndex);
    }

    return rect;
  },
  polar: function (data, dataIndex, itemModel, layout, isRadial, animationModel, isUpdate) {
    // Keep the same logic with bar in catesion: use end value to control
    // direction. Notice that if clockwise is true (by default), the sector
    // will always draw clockwisely, no matter whether endAngle is greater
    // or less than startAngle.
    var clockwise = layout.startAngle < layout.endAngle;
    var sector = new graphic.Sector({
      shape: zrUtil.defaults({
        clockwise: clockwise
      }, layout)
    }); // Animation

    if (animationModel) {
      var sectorShape = sector.shape;
      var animateProperty = isRadial ? 'r' : 'endAngle';
      var animateTarget = {};
      sectorShape[animateProperty] = isRadial ? 0 : layout.startAngle;
      animateTarget[animateProperty] = layout[animateProperty];
      graphic[isUpdate ? 'updateProps' : 'initProps'](sector, {
        shape: animateTarget
      }, animationModel, dataIndex);
    }

    return sector;
  }
};

function removeRect(dataIndex, animationModel, el) {
  // Not show text when animating
  el.style.text = null;
  graphic.updateProps(el, {
    shape: {
      width: 0
    }
  }, animationModel, dataIndex, function () {
    el.parent && el.parent.remove(el);
  });
}

function removeSector(dataIndex, animationModel, el) {
  // Not show text when animating
  el.style.text = null;
  graphic.updateProps(el, {
    shape: {
      r: el.shape.r0
    }
  }, animationModel, dataIndex, function () {
    el.parent && el.parent.remove(el);
  });
}

var getLayout = {
  cartesian2d: function (data, dataIndex, itemModel) {
    var layout = data.getItemLayout(dataIndex);
    var fixedLineWidth = getLineWidth(itemModel, layout); // fix layout with lineWidth

    var signX = layout.width > 0 ? 1 : -1;
    var signY = layout.height > 0 ? 1 : -1;
    return {
      x: layout.x + signX * fixedLineWidth / 2,
      y: layout.y + signY * fixedLineWidth / 2,
      width: layout.width - signX * fixedLineWidth,
      height: layout.height - signY * fixedLineWidth
    };
  },
  polar: function (data, dataIndex, itemModel) {
    var layout = data.getItemLayout(dataIndex);
    return {
      cx: layout.cx,
      cy: layout.cy,
      r0: layout.r0,
      r: layout.r,
      startAngle: layout.startAngle,
      endAngle: layout.endAngle
    };
  }
};

function updateStyle(el, data, dataIndex, itemModel, layout, seriesModel, isHorizontal, isPolar) {
  var color = data.getItemVisual(dataIndex, 'color');
  var opacity = data.getItemVisual(dataIndex, 'opacity');
  var itemStyleModel = itemModel.getModel('itemStyle');
  var hoverStyle = itemModel.getModel('emphasis.itemStyle').getBarItemStyle();

  if (!isPolar) {
    el.setShape('r', itemStyleModel.get('barBorderRadius') || 0);
  }

  el.useStyle(zrUtil.defaults({
    fill: color,
    opacity: opacity
  }, itemStyleModel.getBarItemStyle()));
  var cursorStyle = itemModel.getShallow('cursor');
  cursorStyle && el.attr('cursor', cursorStyle);
  var labelPositionOutside = isHorizontal ? layout.height > 0 ? 'bottom' : 'top' : layout.width > 0 ? 'left' : 'right';

  if (!isPolar) {
    setLabel(el.style, hoverStyle, itemModel, color, seriesModel, dataIndex, labelPositionOutside);
  }

  graphic.setHoverStyle(el, hoverStyle);
} // In case width or height are too small.


function getLineWidth(itemModel, rawLayout) {
  var lineWidth = itemModel.get(BAR_BORDER_WIDTH_QUERY) || 0;
  return Math.min(lineWidth, Math.abs(rawLayout.width), Math.abs(rawLayout.height));
}

var LargePath = Path.extend({
  type: 'largeBar',
  shape: {
    points: []
  },
  buildPath: function (ctx, shape) {
    // Drawing lines is more efficient than drawing
    // a whole line or drawing rects.
    var points = shape.points;
    var startPoint = this.__startPoint;
    var baseDimIdx = this.__baseDimIdx;

    for (var i = 0; i < points.length; i += 2) {
      startPoint[baseDimIdx] = points[i + baseDimIdx];
      ctx.moveTo(startPoint[0], startPoint[1]);
      ctx.lineTo(points[i], points[i + 1]);
    }
  }
});

function createLarge(seriesModel, group, incremental) {
  // TODO support polar
  var data = seriesModel.getData();
  var startPoint = [];
  var baseDimIdx = data.getLayout('valueAxisHorizontal') ? 1 : 0;
  startPoint[1 - baseDimIdx] = data.getLayout('valueAxisStart');
  var el = new LargePath({
    shape: {
      points: data.getLayout('largePoints')
    },
    incremental: !!incremental,
    __startPoint: startPoint,
    __baseDimIdx: baseDimIdx,
    __largeDataIndices: data.getLayout('largeDataIndices'),
    __barWidth: data.getLayout('barWidth')
  });
  group.add(el);
  setLargeStyle(el, seriesModel, data); // Enable tooltip and user mouse/touch event handlers.

  el.seriesIndex = seriesModel.seriesIndex;

  if (!seriesModel.get('silent')) {
    el.on('mousedown', largePathUpdateDataIndex);
    el.on('mousemove', largePathUpdateDataIndex);
  }
} // Use throttle to avoid frequently traverse to find dataIndex.


var largePathUpdateDataIndex = throttle(function (event) {
  var largePath = this;
  var dataIndex = largePathFindDataIndex(largePath, event.offsetX, event.offsetY);
  largePath.dataIndex = dataIndex >= 0 ? dataIndex : null;
}, 30, false);

function largePathFindDataIndex(largePath, x, y) {
  var baseDimIdx = largePath.__baseDimIdx;
  var valueDimIdx = 1 - baseDimIdx;
  var points = largePath.shape.points;
  var largeDataIndices = largePath.__largeDataIndices;
  var barWidthHalf = Math.abs(largePath.__barWidth / 2);
  var startValueVal = largePath.__startPoint[valueDimIdx];
  _eventPos[0] = x;
  _eventPos[1] = y;
  var pointerBaseVal = _eventPos[baseDimIdx];
  var pointerValueVal = _eventPos[1 - baseDimIdx];
  var baseLowerBound = pointerBaseVal - barWidthHalf;
  var baseUpperBound = pointerBaseVal + barWidthHalf;

  for (var i = 0, len = points.length / 2; i < len; i++) {
    var ii = i * 2;
    var barBaseVal = points[ii + baseDimIdx];
    var barValueVal = points[ii + valueDimIdx];

    if (barBaseVal >= baseLowerBound && barBaseVal <= baseUpperBound && (startValueVal <= barValueVal ? pointerValueVal >= startValueVal && pointerValueVal <= barValueVal : pointerValueVal >= barValueVal && pointerValueVal <= startValueVal)) {
      return largeDataIndices[i];
    }
  }

  return -1;
}

function setLargeStyle(el, seriesModel, data) {
  var borderColor = data.getVisual('borderColor') || data.getVisual('color');
  var itemStyle = seriesModel.getModel('itemStyle').getItemStyle(['color', 'borderColor']);
  el.useStyle(itemStyle);
  el.style.fill = null;
  el.style.stroke = borderColor;
  el.style.lineWidth = data.getLayout('barWidth');
}