
/*
* 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.
 */

import { __extends } from "tslib";
import PointerPath from './PointerPath';
import * as graphic from '../../util/graphic';
import { setStatesStylesFromModel, enableHoverEmphasis } from '../../util/states';
import { createTextStyle } from '../../label/labelStyle';
import ChartView from '../../view/Chart';
import { parsePercent, round, linearMap } from '../../util/number';

function parsePosition(seriesModel, api) {
  var center = seriesModel.get('center');
  var width = api.getWidth();
  var height = api.getHeight();
  var size = Math.min(width, height);
  var cx = parsePercent(center[0], api.getWidth());
  var cy = parsePercent(center[1], api.getHeight());
  var r = parsePercent(seriesModel.get('radius'), size / 2);
  return {
    cx: cx,
    cy: cy,
    r: r
  };
}

function formatLabel(value, labelFormatter) {
  var label = value == null ? '' : value + '';

  if (labelFormatter) {
    if (typeof labelFormatter === 'string') {
      label = labelFormatter.replace('{value}', label);
    } else if (typeof labelFormatter === 'function') {
      label = labelFormatter(value);
    }
  }

  return label;
}

var PI2 = Math.PI * 2;

var GaugeView = function (_super) {
  __extends(GaugeView, _super);

  function GaugeView() {
    var _this = _super !== null && _super.apply(this, arguments) || this;

    _this.type = GaugeView.type;
    return _this;
  }

  GaugeView.prototype.render = function (seriesModel, ecModel, api) {
    this.group.removeAll();
    var colorList = seriesModel.get(['axisLine', 'lineStyle', 'color']);
    var posInfo = parsePosition(seriesModel, api);

    this._renderMain(seriesModel, ecModel, api, colorList, posInfo);
  };

  GaugeView.prototype.dispose = function () {};

  GaugeView.prototype._renderMain = function (seriesModel, ecModel, api, colorList, posInfo) {
    var group = this.group;
    var axisLineModel = seriesModel.getModel('axisLine');
    var lineStyleModel = axisLineModel.getModel('lineStyle');
    var clockwise = seriesModel.get('clockwise');
    var startAngle = -seriesModel.get('startAngle') / 180 * Math.PI;
    var endAngle = -seriesModel.get('endAngle') / 180 * Math.PI;
    var angleRangeSpan = (endAngle - startAngle) % PI2;
    var prevEndAngle = startAngle;
    var axisLineWidth = lineStyleModel.get('width');
    var showAxis = axisLineModel.get('show');

    for (var i = 0; showAxis && i < colorList.length; i++) {
      var percent = Math.min(Math.max(colorList[i][0], 0), 1);
      endAngle = startAngle + angleRangeSpan * percent;
      var sector = new graphic.Sector({
        shape: {
          startAngle: prevEndAngle,
          endAngle: endAngle,
          cx: posInfo.cx,
          cy: posInfo.cy,
          clockwise: clockwise,
          r0: posInfo.r - axisLineWidth,
          r: posInfo.r
        },
        silent: true
      });
      sector.setStyle({
        fill: colorList[i][1]
      });
      sector.setStyle(lineStyleModel.getLineStyle(['color', 'width']));
      group.add(sector);
      prevEndAngle = endAngle;
    }

    var getColor = function (percent) {
      if (percent <= 0) {
        return colorList[0][1];
      }

      var i;

      for (i = 0; i < colorList.length; i++) {
        if (colorList[i][0] >= percent && (i === 0 ? 0 : colorList[i - 1][0]) < percent) {
          return colorList[i][1];
        }
      }

      return colorList[i - 1][1];
    };

    if (!clockwise) {
      var tmp = startAngle;
      startAngle = endAngle;
      endAngle = tmp;
    }

    this._renderTicks(seriesModel, ecModel, api, getColor, posInfo, startAngle, endAngle, clockwise);

    this._renderPointer(seriesModel, ecModel, api, getColor, posInfo, startAngle, endAngle, clockwise);

    this._renderTitle(seriesModel, ecModel, api, getColor, posInfo);

    this._renderDetail(seriesModel, ecModel, api, getColor, posInfo);
  };

  GaugeView.prototype._renderTicks = function (seriesModel, ecModel, api, getColor, posInfo, startAngle, endAngle, clockwise) {
    var group = this.group;
    var cx = posInfo.cx;
    var cy = posInfo.cy;
    var r = posInfo.r;
    var minVal = +seriesModel.get('min');
    var maxVal = +seriesModel.get('max');
    var splitLineModel = seriesModel.getModel('splitLine');
    var tickModel = seriesModel.getModel('axisTick');
    var labelModel = seriesModel.getModel('axisLabel');
    var splitNumber = seriesModel.get('splitNumber');
    var subSplitNumber = tickModel.get('splitNumber');
    var splitLineLen = parsePercent(splitLineModel.get('length'), r);
    var tickLen = parsePercent(tickModel.get('length'), r);
    var angle = startAngle;
    var step = (endAngle - startAngle) / splitNumber;
    var subStep = step / subSplitNumber;
    var splitLineStyle = splitLineModel.getModel('lineStyle').getLineStyle();
    var tickLineStyle = tickModel.getModel('lineStyle').getLineStyle();
    var unitX;
    var unitY;

    for (var i = 0; i <= splitNumber; i++) {
      unitX = Math.cos(angle);
      unitY = Math.sin(angle);

      if (splitLineModel.get('show')) {
        var splitLine = new graphic.Line({
          shape: {
            x1: unitX * r + cx,
            y1: unitY * r + cy,
            x2: unitX * (r - splitLineLen) + cx,
            y2: unitY * (r - splitLineLen) + cy
          },
          style: splitLineStyle,
          silent: true
        });

        if (splitLineStyle.stroke === 'auto') {
          splitLine.setStyle({
            stroke: getColor(i / splitNumber)
          });
        }

        group.add(splitLine);
      }

      if (labelModel.get('show')) {
        var label = formatLabel(round(i / splitNumber * (maxVal - minVal) + minVal), labelModel.get('formatter'));
        var distance = labelModel.get('distance');
        var autoColor = getColor(i / splitNumber);
        group.add(new graphic.Text({
          style: createTextStyle(labelModel, {
            text: label,
            x: unitX * (r - splitLineLen - distance) + cx,
            y: unitY * (r - splitLineLen - distance) + cy,
            verticalAlign: unitY < -0.4 ? 'top' : unitY > 0.4 ? 'bottom' : 'middle',
            align: unitX < -0.4 ? 'left' : unitX > 0.4 ? 'right' : 'center'
          }, {
            inheritColor: autoColor
          }),
          silent: true
        }));
      }

      if (tickModel.get('show') && i !== splitNumber) {
        for (var j = 0; j <= subSplitNumber; j++) {
          unitX = Math.cos(angle);
          unitY = Math.sin(angle);
          var tickLine = new graphic.Line({
            shape: {
              x1: unitX * r + cx,
              y1: unitY * r + cy,
              x2: unitX * (r - tickLen) + cx,
              y2: unitY * (r - tickLen) + cy
            },
            silent: true,
            style: tickLineStyle
          });

          if (tickLineStyle.stroke === 'auto') {
            tickLine.setStyle({
              stroke: getColor((i + j / subSplitNumber) / splitNumber)
            });
          }

          group.add(tickLine);
          angle += subStep;
        }

        angle -= subStep;
      } else {
        angle += step;
      }
    }
  };

  GaugeView.prototype._renderPointer = function (seriesModel, ecModel, api, getColor, posInfo, startAngle, endAngle, clockwise) {
    var group = this.group;
    var oldData = this._data;

    if (!seriesModel.get(['pointer', 'show'])) {
      oldData && oldData.eachItemGraphicEl(function (el) {
        group.remove(el);
      });
      return;
    }

    var valueExtent = [+seriesModel.get('min'), +seriesModel.get('max')];
    var angleExtent = [startAngle, endAngle];
    var data = seriesModel.getData();
    var valueDim = data.mapDimension('value');
    data.diff(oldData).add(function (idx) {
      var pointer = new PointerPath({
        shape: {
          angle: startAngle
        }
      });
      graphic.initProps(pointer, {
        shape: {
          angle: linearMap(data.get(valueDim, idx), valueExtent, angleExtent, true)
        }
      }, seriesModel);
      group.add(pointer);
      data.setItemGraphicEl(idx, pointer);
    }).update(function (newIdx, oldIdx) {
      var pointer = oldData.getItemGraphicEl(oldIdx);
      graphic.updateProps(pointer, {
        shape: {
          angle: linearMap(data.get(valueDim, newIdx), valueExtent, angleExtent, true)
        }
      }, seriesModel);
      group.add(pointer);
      data.setItemGraphicEl(newIdx, pointer);
    }).remove(function (idx) {
      var pointer = oldData.getItemGraphicEl(idx);
      group.remove(pointer);
    }).execute();
    data.eachItemGraphicEl(function (pointer, idx) {
      var itemModel = data.getItemModel(idx);
      var pointerModel = itemModel.getModel('pointer');
      var emphasisModel = itemModel.getModel('emphasis');
      pointer.setShape({
        x: posInfo.cx,
        y: posInfo.cy,
        width: parsePercent(pointerModel.get('width'), posInfo.r),
        r: parsePercent(pointerModel.get('length'), posInfo.r)
      });
      pointer.useStyle(itemModel.getModel('itemStyle').getItemStyle());

      if (pointer.style.fill === 'auto') {
        pointer.setStyle('fill', getColor(linearMap(data.get(valueDim, idx), valueExtent, [0, 1], true)));
      }

      setStatesStylesFromModel(pointer, itemModel);
      enableHoverEmphasis(pointer, emphasisModel.get('focus'), emphasisModel.get('blurScope'));
    });
    this._data = data;
  };

  GaugeView.prototype._renderTitle = function (seriesModel, ecModel, api, getColor, posInfo) {
    var data = seriesModel.getData();
    var valueDim = data.mapDimension('value');
    var titleModel = seriesModel.getModel('title');

    if (titleModel.get('show')) {
      var offsetCenter = titleModel.get('offsetCenter');
      var x = posInfo.cx + parsePercent(offsetCenter[0], posInfo.r);
      var y = posInfo.cy + parsePercent(offsetCenter[1], posInfo.r);
      var minVal = +seriesModel.get('min');
      var maxVal = +seriesModel.get('max');
      var value = seriesModel.getData().get(valueDim, 0);
      var autoColor = getColor(linearMap(value, [minVal, maxVal], [0, 1], true));
      this.group.add(new graphic.Text({
        silent: true,
        style: createTextStyle(titleModel, {
          x: x,
          y: y,
          text: data.getName(0),
          align: 'center',
          verticalAlign: 'middle'
        }, {
          inheritColor: autoColor
        })
      }));
    }
  };

  GaugeView.prototype._renderDetail = function (seriesModel, ecModel, api, getColor, posInfo) {
    var detailModel = seriesModel.getModel('detail');
    var minVal = +seriesModel.get('min');
    var maxVal = +seriesModel.get('max');

    if (detailModel.get('show')) {
      var offsetCenter = detailModel.get('offsetCenter');
      var x = posInfo.cx + parsePercent(offsetCenter[0], posInfo.r);
      var y = posInfo.cy + parsePercent(offsetCenter[1], posInfo.r);
      var width = parsePercent(detailModel.get('width'), posInfo.r);
      var height = parsePercent(detailModel.get('height'), posInfo.r);
      var data = seriesModel.getData();
      var value = data.get(data.mapDimension('value'), 0);
      var autoColor = getColor(linearMap(value, [minVal, maxVal], [0, 1], true));
      this.group.add(new graphic.Text({
        silent: true,
        style: createTextStyle(detailModel, {
          x: x,
          y: y,
          text: formatLabel(value, detailModel.get('formatter')),
          width: isNaN(width) ? null : width,
          height: isNaN(height) ? null : height,
          align: 'center',
          verticalAlign: 'middle'
        }, {
          inheritColor: autoColor
        })
      }));
    }
  };

  GaugeView.type = 'gauge';
  return GaugeView;
}(ChartView);

ChartView.registerClass(GaugeView);
export default GaugeView;