'use strict';

var number = require('../util/number.js');
var Interval = require('../scale/Interval.js');
var axisHelper = require('./axisHelper.js');
var log = require('../util/log.js');
var helper = require('../scale/helper.js');

function alignScaleTicks(scale, axisModel, alignToScale) {
  var _a;
  var intervalScaleProto = Interval.default.prototype;
  // NOTE: There is a precondition for log scale  here:
  // In log scale we store _interval and _extent of exponent value.
  // So if we use the method of InternalScale to set/get these data.
  // It process the exponent value, which is linear and what we want here.
  var alignToTicks = intervalScaleProto.getTicks.call(alignToScale);
  var alignToNicedTicks = intervalScaleProto.getTicks.call(alignToScale, {
    expandToNicedExtent: true
  });
  var alignToSplitNumber = alignToTicks.length - 1;
  var alignToInterval = intervalScaleProto.getInterval.call(alignToScale);
  var scaleExtent = axisHelper.getScaleExtent(scale, axisModel);
  var rawExtent = scaleExtent.extent;
  var isMinFixed = scaleExtent.fixMin;
  var isMaxFixed = scaleExtent.fixMax;
  if (scale.type === 'log') {
    rawExtent = helper.logTransform(scale.base, rawExtent, true);
  }
  scale.setBreaksFromOption(axisHelper.retrieveAxisBreaksOption(axisModel));
  scale.setExtent(rawExtent[0], rawExtent[1]);
  scale.calcNiceExtent({
    splitNumber: alignToSplitNumber,
    fixMin: isMinFixed,
    fixMax: isMaxFixed
  });
  var extent = intervalScaleProto.getExtent.call(scale);
  // Need to update the rawExtent.
  // Because value in rawExtent may be not parsed. e.g. 'dataMin', 'dataMax'
  if (isMinFixed) {
    rawExtent[0] = extent[0];
  }
  if (isMaxFixed) {
    rawExtent[1] = extent[1];
  }
  var interval = intervalScaleProto.getInterval.call(scale);
  var min = rawExtent[0];
  var max = rawExtent[1];
  if (isMinFixed && isMaxFixed) {
    // User set min, max, divide to get new interval
    interval = (max - min) / alignToSplitNumber;
  } else if (isMinFixed) {
    max = rawExtent[0] + interval * alignToSplitNumber;
    // User set min, expand extent on the other side
    while (max < rawExtent[1] && isFinite(max) && isFinite(rawExtent[1])) {
      interval = helper.increaseInterval(interval);
      max = rawExtent[0] + interval * alignToSplitNumber;
    }
  } else if (isMaxFixed) {
    // User set max, expand extent on the other side
    min = rawExtent[1] - interval * alignToSplitNumber;
    while (min > rawExtent[0] && isFinite(min) && isFinite(rawExtent[0])) {
      interval = helper.increaseInterval(interval);
      min = rawExtent[1] - interval * alignToSplitNumber;
    }
  } else {
    var nicedSplitNumber = scale.getTicks().length - 1;
    if (nicedSplitNumber > alignToSplitNumber) {
      interval = helper.increaseInterval(interval);
    }
    var range = interval * alignToSplitNumber;
    max = Math.ceil(rawExtent[1] / interval) * interval;
    min = number.round(max - range);
    // Not change the result that crossing zero.
    if (min < 0 && rawExtent[0] >= 0) {
      min = 0;
      max = number.round(range);
    } else if (max > 0 && rawExtent[1] <= 0) {
      max = 0;
      min = -number.round(range);
    }
  }
  // Adjust min, max based on the extent of alignTo. When min or max is set in alignTo scale
  var t0 = (alignToTicks[0].value - alignToNicedTicks[0].value) / alignToInterval;
  var t1 = (alignToTicks[alignToSplitNumber].value - alignToNicedTicks[alignToSplitNumber].value) / alignToInterval;
  // NOTE: Must in setExtent -> setInterval -> setNiceExtent order.
  intervalScaleProto.setExtent.call(scale, min + interval * t0, max + interval * t1);
  intervalScaleProto.setInterval.call(scale, interval);
  if (t0 || t1) {
    intervalScaleProto.setNiceExtent.call(scale, min + interval, max - interval);
  }
  if (process.env.NODE_ENV !== 'production') {
    var ticks = intervalScaleProto.getTicks.call(scale);
    if (ticks[1] && (!helper.isValueNice(interval) || number.getPrecisionSafe(ticks[1].value) > number.getPrecisionSafe(interval))) {
      log.warn("The ticks may be not readable when set min: " + axisModel.get('min') + ", max: " + axisModel.get('max') + (" and alignTicks: true. (" + ((_a = axisModel.axis) === null || _a === void 0 ? void 0 : _a.dim) + "AxisIndex: " + axisModel.componentIndex + ")"), true);
    }
  }
}

exports.alignScaleTicks = alignScaleTicks;
