/**
 * @fileOverview 使用pow进行度量计算
 * @author dxq613@gmail.com
 */
const Base = require('./base');
const Linear = require('./linear');

// 求以a为次幂，结果为b的基数，如 x^^a = b;求x
function calBase(a, b) {
  const e = Math.E;
  const value = Math.pow(e, Math.log(b) / a); // 使用换底公式求底
  return value;
}

/**
 * 度量的Pow计算
 * @class Scale.Log
 */
class Pow extends Linear {

  _initDefaultCfg() {
    super._initDefaultCfg();

    this.type = 'pow';
    /**
     * @override
     * pow 的坐标点的个数控制在10个以下
     * @type {Number}
     */
    this.tickCount = 10;
    /**
     * 进行pow计算的基数
     * @type {Number}
     */
    this.exponent = 2;
  }

  /**
   * @override
   */
  calculateTicks() {
    const self = this;
    const exponent = self.exponent;
    let min;
    let max = Math.ceil(calBase(exponent, self.max));

    if (self.min >= 0) {
      min = Math.floor(calBase(exponent, self.min));
    } else {
      min = 0;
    }
    if (min > max) {
      const tmp = max;
      max = min;
      min = tmp;
    }
    const count = max - min;
    const tickCount = self.tickCount;
    const avg = Math.ceil(count / tickCount);
    const ticks = [];

    for (let i = min; i < max + avg; i = i + avg) {
      ticks.push(Math.pow(i, exponent));
    }
    return ticks;
  }

  // 获取度量计算时，value占的定义域百分比
  _getScalePercent(value) {
    const max = this.max;
    const min = this.min;
    if (max === min) {
      return 0;
    }
    const exponent = this.exponent;
    const percent = (calBase(exponent, value) - calBase(exponent, min)) / (calBase(exponent, max) - calBase(exponent, min));
    return percent;
  }

  /**
   * @override
   */
  scale(value) {
    const percent = this._getScalePercent(value);
    const rangeMin = this.rangeMin();
    const rangeMax = this.rangeMax();
    return rangeMin + percent * (rangeMax - rangeMin);
  }

  /**
   * @override
   */
  invert(value) {
    const percent = (value - this.rangeMin()) / (this.rangeMax() - this.rangeMin());
    const exponent = this.exponent;
    const max = calBase(exponent, this.max);
    const min = calBase(exponent, this.min);
    const tmp = percent * (max - min) + min;
    return Math.pow(tmp, exponent);
  }
}

Base.Pow = Pow;
module.exports = Pow;
