
/*
* 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";
import { each, createHashMap, merge, assert } from 'tvrender/lib/core/util.js';
import ComponentModel from '../../model/Component.js';
import { getAxisMainType, DATA_ZOOM_AXIS_DIMENSIONS } from './helper.js';
import { MULTIPLE_REFERRING, SINGLE_REFERRING } from '../../util/model.js';
import { getLayoutRect } from '../../util/layout.js';
var DataZoomAxisInfo = /** @class */function () {
  function DataZoomAxisInfo() {
    this.indexList = [];
    this.indexMap = [];
  }
  DataZoomAxisInfo.prototype.add = function (axisCmptIdx) {
    // Remove duplication.
    if (!this.indexMap[axisCmptIdx]) {
      this.indexList.push(axisCmptIdx);
      this.indexMap[axisCmptIdx] = true;
    }
  };
  return DataZoomAxisInfo;
}();
var DefaultBarSpace = 6;
var DefaultOffsetRightDistance = 50;
var DataZoomModel = /** @class */function (_super) {
  __extends(DataZoomModel, _super);
  function DataZoomModel() {
    var _this = _super !== null && _super.apply(this, arguments) || this;
    _this.type = DataZoomModel.type;
    _this._distanceRange = [DefaultBarSpace, DefaultOffsetRightDistance / DefaultBarSpace];
    _this._autoThrottle = true;
    _this._noTarget = true;
    /**
     * It is `[rangeModeForMin, rangeModeForMax]`.
     * The optional values for `rangeMode`:
     * + `'value'` mode: the axis extent will always be determined by
     *     `dataZoom.startValue` and `dataZoom.endValue`, despite
     *     how data like and how `axis.min` and `axis.max` are.
     * + `'percent'` mode: `100` represents 100% of the `[dMin, dMax]`,
     *     where `dMin` is `axis.min` if `axis.min` specified, otherwise `data.extent[0]`,
     *     and `dMax` is `axis.max` if `axis.max` specified, otherwise `data.extent[1]`.
     *     Axis extent will be determined by the result of the percent of `[dMin, dMax]`.
     *
     * For example, when users are using dynamic data (update data periodically via `setOption`),
     * if in `'value`' mode, the window will be kept in a fixed value range despite how
     * data are appended, while if in `'percent'` mode, whe window range will be changed alone with
     * the appended data (suppose `axis.min` and `axis.max` are not specified).
     */
    _this._rangePropMode = ['percent', 'percent'];
    return _this;
  }
  DataZoomModel.prototype.init = function (option, parentModel, ecModel) {
    var inputRawOption = retrieveRawOption(option);
    /**
     * Suppose a "main process" start at the point that model prepared (that is,
     * model initialized or merged or method called in `action`).
     * We should keep the `main process` idempotent, that is, given a set of values
     * on `option`, we get the same result.
     *
     * But sometimes, values on `option` will be updated for providing users
     * a "final calculated value" (`dataZoomProcessor` will do that). Those value
     * should not be the base/input of the `main process`.
     *
     * So in that case we should save and keep the input of the `main process`
     * separately, called `settledOption`.
     *
     * For example, consider the case:
     * (Step_1) brush zoom the grid by `toolbox.dataZoom`,
     *     where the original input `option.startValue`, `option.endValue` are earsed by
     *     calculated value.
     * (Step)2) click the legend to hide and show a series,
     *     where the new range is calculated by the earsed `startValue` and `endValue`,
     *     which brings incorrect result.
     */
    this.settledOption = inputRawOption;
    this.mergeDefaultAndTheme(option, ecModel);
    this._doInit(inputRawOption);
  };
  DataZoomModel.prototype.mergeOption = function (newOption, ecModel) {
    var inputRawOption = retrieveRawOption(newOption);
    // FIX #2591
    merge(this.option, newOption, true);
    merge(this.settledOption, inputRawOption, true);
    this._doInit(inputRawOption);
  };
  DataZoomModel.prototype._doInit = function (inputRawOption) {
    var thisOption = this.option;
    this._setDefaultThrottle(inputRawOption);
    this._updateRangeUse(inputRawOption);
    var settledOption = this.settledOption;
    each([['start', 'startValue'], ['end', 'endValue']], function (names, index) {
      // start/end has higher priority over startValue/endValue if they
      // both set, but we should make chart.setOption({endValue: 1000})
      // effective, rather than chart.setOption({endValue: 1000, end: null}).
      if (this._rangePropMode[index] === 'value') {
        thisOption[names[0]] = settledOption[names[0]] = null;
      }
      // Otherwise do nothing and use the merge result.
    }, this);
    // console.log('%c [ thisOption ]-297', 'font-size:13px; background:pink; color:#bf2c9f;', thisOption.barSpace)
    this._resetTarget();
    this._initBarSpace(inputRawOption);
  };
  DataZoomModel.prototype._resetTarget = function () {
    var optionOrient = this.get('orient', true);
    var targetAxisIndexMap = this._targetAxisInfoMap = createHashMap();
    var hasAxisSpecified = this._fillSpecifiedTargetAxis(targetAxisIndexMap);
    if (hasAxisSpecified) {
      this._orient = optionOrient || this._makeAutoOrientByTargetAxis();
    } else {
      this._orient = optionOrient || 'horizontal';
      this._fillAutoTargetAxisByOrient(targetAxisIndexMap, this._orient);
    }
    this._noTarget = true;
    targetAxisIndexMap.each(function (axisInfo) {
      if (axisInfo.indexList.length) {
        this._noTarget = false;
      }
    }, this);
  };
  DataZoomModel.prototype._getBarSpaceByShowBarCount = function (showBarCount) {
    var axisModal = this.getFirstTargetAxisModel();
    // console.log('%c [ axisModal ]-318', 'font-size:13px; background:pink; color:#bf2c9f;',this, axisModal.grid, axisModal.axis)
    var gridModel = this.ecModel.getComponent('grid', 0);
    // const rect = grid.coordinateSystem.getRect();
    if (axisModal && axisModal.axis) {
      var width = axisModal.axis.getExtent()[1];
      return width / showBarCount;
    } else if (gridModel) {
      var api = this.ecModel.scheduler.api;
      var boxLayoutParams = gridModel.getBoxLayoutParams();
      var gridRect = getLayoutRect(boxLayoutParams, {
        width: api.getWidth(),
        height: api.getHeight()
      });
      return gridRect.width / showBarCount;
    }
    return;
  };
  DataZoomModel.prototype._initBarSpace = function (inputRawOption) {
    var _a;
    var barSpace = inputRawOption.barSpace;
    // if (inputRawOption.autoBarSpace) {
    //     this.option.autoBarSpace = inputRawOption.autoBarSpace;
    // }
    if (inputRawOption.showBarCount) {
      this.option.showBarCount = inputRawOption.showBarCount;
    }
    // if (inputRawOption.autoBarSpace) {
    //     this.option.showBarCount = inputRawOption.showBarCount;
    //     const autoBarSpace = this._getBarSpaceByShowBarCount(inputRawOption.showBarCount);
    //     if (autoBarSpace) {
    //         barSpace = autoBarSpace;
    //     }
    // }
    if (barSpace) {
      this.option.barSpace = barSpace;
    }
    if (inputRawOption.lastBarRightSideDiffBarCount !== void 0) {
      this.option.lastBarRightSideDiffBarCount = inputRawOption.lastBarRightSideDiffBarCount;
    }
    if (inputRawOption.barSpace || inputRawOption.lastBarRightSideDiffBarCount !== void 0) {
      this.setDistanceRange([barSpace !== null && barSpace !== void 0 ? barSpace : this.option.barSpace, (_a = inputRawOption.lastBarRightSideDiffBarCount) !== null && _a !== void 0 ? _a : this.option.lastBarRightSideDiffBarCount]);
    }
  };
  DataZoomModel.prototype._fillSpecifiedTargetAxis = function (targetAxisIndexMap) {
    var hasAxisSpecified = false;
    each(DATA_ZOOM_AXIS_DIMENSIONS, function (axisDim) {
      var refering = this.getReferringComponents(getAxisMainType(axisDim), MULTIPLE_REFERRING);
      // When user set axisIndex as a empty array, we think that user specify axisIndex
      // but do not want use auto mode. Because empty array may be encountered when
      // some error occurred.
      if (!refering.specified) {
        return;
      }
      hasAxisSpecified = true;
      var axisInfo = new DataZoomAxisInfo();
      each(refering.models, function (axisModel) {
        axisInfo.add(axisModel.componentIndex);
      });
      targetAxisIndexMap.set(axisDim, axisInfo);
    }, this);
    return hasAxisSpecified;
  };
  DataZoomModel.prototype._fillAutoTargetAxisByOrient = function (targetAxisIndexMap, orient) {
    var ecModel = this.ecModel;
    var needAuto = true;
    // Find axis that parallel to dataZoom as default.
    if (needAuto) {
      var axisDim = orient === 'vertical' ? 'y' : 'x';
      var axisModels = ecModel.findComponents({
        mainType: axisDim + 'Axis'
      });
      setParallelAxis(axisModels, axisDim);
    }
    // Find axis that parallel to dataZoom as default.
    if (needAuto) {
      var axisModels = ecModel.findComponents({
        mainType: 'singleAxis',
        filter: function (axisModel) {
          return axisModel.get('orient', true) === orient;
        }
      });
      setParallelAxis(axisModels, 'single');
    }
    function setParallelAxis(axisModels, axisDim) {
      // At least use the first parallel axis as the target axis.
      var axisModel = axisModels[0];
      if (!axisModel) {
        return;
      }
      var axisInfo = new DataZoomAxisInfo();
      axisInfo.add(axisModel.componentIndex);
      targetAxisIndexMap.set(axisDim, axisInfo);
      needAuto = false;
      // Find parallel axes in the same grid.
      if (axisDim === 'x' || axisDim === 'y') {
        var gridModel_1 = axisModel.getReferringComponents('grid', SINGLE_REFERRING).models[0];
        gridModel_1 && each(axisModels, function (axModel) {
          if (axisModel.componentIndex !== axModel.componentIndex && gridModel_1 === axModel.getReferringComponents('grid', SINGLE_REFERRING).models[0]) {
            axisInfo.add(axModel.componentIndex);
          }
        });
      }
    }
    if (needAuto) {
      // If no parallel axis, find the first category axis as default. (Also consider polar).
      each(DATA_ZOOM_AXIS_DIMENSIONS, function (axisDim) {
        if (!needAuto) {
          return;
        }
        var axisModels = ecModel.findComponents({
          mainType: getAxisMainType(axisDim),
          filter: function (axisModel) {
            return axisModel.get('type', true) === 'category';
          }
        });
        if (axisModels[0]) {
          var axisInfo = new DataZoomAxisInfo();
          axisInfo.add(axisModels[0].componentIndex);
          targetAxisIndexMap.set(axisDim, axisInfo);
          needAuto = false;
        }
      }, this);
    }
  };
  DataZoomModel.prototype._makeAutoOrientByTargetAxis = function () {
    var dim;
    // Find the first axis
    this.eachTargetAxis(function (axisDim) {
      !dim && (dim = axisDim);
    }, this);
    return dim === 'y' ? 'vertical' : 'horizontal';
  };
  DataZoomModel.prototype._setDefaultThrottle = function (inputRawOption) {
    // When first time user set throttle, auto throttle ends.
    if (inputRawOption.hasOwnProperty('throttle')) {
      this._autoThrottle = false;
    }
    if (this._autoThrottle) {
      var globalOption = this.ecModel.option;
      this.option.throttle = globalOption.animation && globalOption.animationDurationUpdate > 0 ? 100 : 16;
    }
  };
  DataZoomModel.prototype._updateRangeUse = function (inputRawOption) {
    var rangePropMode = this._rangePropMode;
    var rangeModeInOption = this.get('rangeMode');
    each([['start', 'startValue'], ['end', 'endValue']], function (names, index) {
      var percentSpecified = inputRawOption[names[0]] != null;
      var valueSpecified = inputRawOption[names[1]] != null;
      if (percentSpecified && !valueSpecified) {
        rangePropMode[index] = 'percent';
      } else if (!percentSpecified && valueSpecified) {
        rangePropMode[index] = 'value';
      } else if (rangeModeInOption) {
        rangePropMode[index] = rangeModeInOption[index];
      } else if (percentSpecified) {
        // percentSpecified && valueSpecified
        rangePropMode[index] = 'percent';
      }
      // else remain its original setting.
    });
  };

  DataZoomModel.prototype.noTarget = function () {
    return this._noTarget;
  };
  DataZoomModel.prototype.getFirstTargetAxisModel = function () {
    var firstAxisModel;
    this.eachTargetAxis(function (axisDim, axisIndex) {
      if (firstAxisModel == null) {
        firstAxisModel = this.ecModel.getComponent(getAxisMainType(axisDim), axisIndex);
      }
    }, this);
    return firstAxisModel;
  };
  /**
   * @param {Function} callback param: axisModel, dimNames, axisIndex, dataZoomModel, ecModel
   */
  DataZoomModel.prototype.eachTargetAxis = function (callback, context) {
    this._targetAxisInfoMap.each(function (axisInfo, axisDim) {
      each(axisInfo.indexList, function (axisIndex) {
        callback.call(context, axisDim, axisIndex);
      });
    });
  };
  /**
   * @return If not found, return null/undefined.
   */
  DataZoomModel.prototype.getAxisProxy = function (axisDim, axisIndex) {
    var axisModel = this.getAxisModel(axisDim, axisIndex);
    if (axisModel) {
      return axisModel.__dzAxisProxy;
    }
  };
  /**
   * @return If not found, return null/undefined.
   */
  DataZoomModel.prototype.getAxisModel = function (axisDim, axisIndex) {
    if (process.env.NODE_ENV !== 'production') {
      assert(axisDim && axisIndex != null);
    }
    var axisInfo = this._targetAxisInfoMap.get(axisDim);
    if (axisInfo && axisInfo.indexMap[axisIndex]) {
      return this.ecModel.getComponent(getAxisMainType(axisDim), axisIndex);
    }
  };
  /**
   * If not specified, set to undefined.
   */
  DataZoomModel.prototype.setRawRange = function (opt, isLocal) {
    var thisOption = this.option;
    var settledOption = this.settledOption;
    each([['start', 'startValue'], ['end', 'endValue']], function (names) {
      // Consider the pair <start, startValue>:
      // If one has value and the other one is `null/undefined`, we both set them
      // to `settledOption`. This strategy enables the feature to clear the original
      // value in `settledOption` to `null/undefined`.
      // But if both of them are `null/undefined`, we do not set them to `settledOption`
      // and keep `settledOption` with the original value. This strategy enables users to
      // only set <end or endValue> but not set <start or startValue> when calling
      // `dispatchAction`.
      // The pair <end, endValue> is treated in the same way.
      if (opt[names[0]] != null || opt[names[1]] != null) {
        thisOption[names[0]] = settledOption[names[0]] = opt[names[0]];
        thisOption[names[1]] = settledOption[names[1]] = opt[names[1]];
      }
    }, this);
    if (typeof opt.barSpace === 'number') {
      // // 如果主动修改了barSpace 则清除showBarCount
      // if (thisOption.showBarCount && opt.barSpace !== thisOption.barSpace) {
      //     thisOption.showBarCount = void 0;
      // }
      thisOption.barSpace = opt.barSpace;
    }
    if (typeof opt.lastBarRightSideDiffBarCount === 'number') {
      thisOption.lastBarRightSideDiffBarCount = opt.lastBarRightSideDiffBarCount;
    }
    if (!isLocal && (typeof opt.barSpace === 'number' || typeof opt.lastBarRightSideDiffBarCount === 'number')) {
      this._distanceRange = [opt.barSpace || thisOption.barSpace, opt.lastBarRightSideDiffBarCount || thisOption.lastBarRightSideDiffBarCount];
    }
    this._updateRangeUse(opt);
  };
  DataZoomModel.prototype.setCalculatedRange = function (opt) {
    var option = this.option;
    each(['start', 'startValue', 'end', 'endValue'], function (name) {
      option[name] = opt[name];
    });
    var barSpace = opt.barSpace;
    // if (option.showBarCount) {
    //     const autoBarSpace = this._getBarSpaceByShowBarCount(option.showBarCount);
    //     if (autoBarSpace) {
    //         barSpace = autoBarSpace;
    //     }
    // }
    if (barSpace !== option.barSpace) {
      option.barSpace = barSpace;
      this._distanceRange[0] = barSpace;
    }
    if (opt.lastBarRightSideDiffBarCount !== option.lastBarRightSideDiffBarCount) {
      option.lastBarRightSideDiffBarCount = opt.lastBarRightSideDiffBarCount;
      this._distanceRange[1] = opt.lastBarRightSideDiffBarCount;
    }
  };
  DataZoomModel.prototype.getPercentRange = function () {
    var axisProxy = this.findRepresentativeAxisProxy();
    if (axisProxy) {
      return axisProxy.getDataPercentWindow();
    }
  };
  /**
   * For example, chart.getModel().getComponent('dataZoom').getValueRange('y', 0);
   *
   * @return [startValue, endValue] value can only be '-' or finite number.
   */
  DataZoomModel.prototype.getValueRange = function (axisDim, axisIndex) {
    if (axisDim == null && axisIndex == null) {
      var axisProxy = this.findRepresentativeAxisProxy();
      if (axisProxy) {
        return axisProxy.getDataValueWindow();
      }
    } else {
      return this.getAxisProxy(axisDim, axisIndex).getDataValueWindow();
    }
  };
  DataZoomModel.prototype.getDistanceRange = function () {
    return this._distanceRange;
  };
  DataZoomModel.prototype.setDistanceRange = function (distanceRange) {
    this._distanceRange = distanceRange;
  };
  /**
   * @param axisModel If axisModel given, find axisProxy
   *      corresponding to the axisModel
   */
  DataZoomModel.prototype.findRepresentativeAxisProxy = function (axisModel) {
    if (axisModel) {
      return axisModel.__dzAxisProxy;
    }
    // Find the first hosted axisProxy
    var firstProxy;
    var axisDimList = this._targetAxisInfoMap.keys();
    for (var i = 0; i < axisDimList.length; i++) {
      var axisDim = axisDimList[i];
      var axisInfo = this._targetAxisInfoMap.get(axisDim);
      for (var j = 0; j < axisInfo.indexList.length; j++) {
        var proxy = this.getAxisProxy(axisDim, axisInfo.indexList[j]);
        if (proxy.hostedBy(this)) {
          return proxy;
        }
        if (!firstProxy) {
          firstProxy = proxy;
        }
      }
    }
    // If no hosted proxy found, still need to return a proxy.
    // This case always happens in toolbox dataZoom, where axes are all hosted by
    // other dataZooms.
    return firstProxy;
  };
  DataZoomModel.prototype.getRangePropMode = function () {
    return this._rangePropMode.slice();
  };
  DataZoomModel.prototype.getOrient = function () {
    if (process.env.NODE_ENV !== 'production') {
      // Should not be called before initialized.
      assert(this._orient);
    }
    return this._orient;
  };
  DataZoomModel.type = 'dataZoom';
  DataZoomModel.dependencies = ['xAxis', 'yAxis', 'radiusAxis', 'angleAxis', 'singleAxis', 'series', 'toolbox'];
  DataZoomModel.defaultOption = {
    // zlevel: 0,
    z: 4,
    filterMode: 'filter',
    // startOffset: 0,
    // endOffset: 0,
    start: 0,
    end: 100,
    barSpace: DefaultBarSpace,
    lastBarRightSideDiffBarCount: DefaultOffsetRightDistance / DefaultBarSpace,
    offsetRightDistance: DefaultOffsetRightDistance
  };
  return DataZoomModel;
}(ComponentModel);
/**
 * Retrieve those raw params from option, which will be cached separately,
 * because they will be overwritten by normalized/calculated values in the main
 * process.
 */
function retrieveRawOption(option) {
  var ret = {};
  each(['start', 'end', 'startValue', 'endValue', 'throttle', 'barSpace', 'lastBarRightSideDiffBarCount', 'showBarCount'], function (name) {
    option.hasOwnProperty(name) && (ret[name] = option[name]);
  });
  return ret;
}
export default DataZoomModel;