/**拉平数组 */
export const treeToArray = <T>(treeNodes: T[]) => {
  let result: T[] = [];

  //递归函数 traverse，用于处理单个节点
  const traverse = (node: any) => {
    const newNode = { ...node };
    delete newNode.children;
    // 将没有子节点的新节点添加到结果数组中
    result.push(newNode);

    // 如果当前节点包含 children 属性（即有子节点）
    if (node.children) {
      node.children.forEach(traverse);
    }
  };

  treeNodes.forEach(traverse);

  return result;
};

/**
 * 线性匀速运动函数
 * @param t 当前时间戳差值
 * @param b 开始进度
 * @param c 结束进度
 * @param d 时长
 *  */
function linear(t: number, b: number, c: number, d: number): number {
  return (c * t) / d + b;
}

/**
 * 平滑移动
 * @param targetY 目标元素
 * @param duration 动画市场
 * @param scrollW 移动距离
 */
export function smoothScrollTo(
  targetY: HTMLDivElement,
  duration: number,
  scrollH: number,
) {
  if (targetY) {
    const start = performance.now();
    const top = targetY.scrollTop;
    function step(timestamp: number) {
      if (timestamp < start + duration) {
        const progress = timestamp - start;
        const linearProgress = linear(progress, 0, 1, duration);

        targetY.scrollTo({
          top: top + scrollH * linearProgress,
        });

        requestAnimationFrame(step);
      }
    }

    requestAnimationFrame(step);
  }
}

/**
 * 最大余额法，计算百分比
 * @param valueList 数值数组
 * @param decimal 保留小数位
 * @example
 * // 输出 ['32.56%', '6.97%', '27.91%', '32.56%']
 * getPercentWithPrecision([56, 12, 48, 56], 2)
 */
export function getPercentWithPrecision(
  valueList: number[],
  precision: number,
) {
  // 根据保留的小数位做对应的放大
  const digits = Math.pow(10, precision);
  const sum = valueList.reduce((total, cur) => total + cur, 0);

  if (sum === 0) {
    return valueList.map(() => 0); // 避免除以零的错误
  }

  // 计算每项占比，并做放大，保证整数部分就是当前获得的席位，小数部分就是余额
  const votesPerQuota = valueList.map((val) => {
    return (val / sum) * 100 * digits;
  });

  // 整数部分就是每项首次分配的席位
  const seats = votesPerQuota.map((val) => {
    return Math.floor(val);
  });

  // 计算各项的余额
  const remainder = votesPerQuota.map((val) => {
    return val - Math.floor(val);
  });

  // 总席位
  const totalSeats = 100 * digits;
  // 当前已经分配出去的席位总数
  let currentSeats = seats.reduce((total, cur) => total + cur, 0);

  // 按最大余额法分配
  while (totalSeats - currentSeats > 0) {
    let maxIdx = -1; // 余数最大的 id
    let maxValue = Number.NEGATIVE_INFINITY; // 最大余额, 初始重置为无穷小

    // 选出这组余额数据中最大值
    for (let i = 0; i < remainder.length; i++) {
      if (maxValue < remainder[i]) {
        maxValue = remainder[i];
        maxIdx = i;
      }
    }

    // 对应的项席位加 1，余额清零，当前分配席位加 1
    seats[maxIdx]++;
    remainder[maxIdx] = 0;
    currentSeats++;
  }

  return seats
    .map((val) => (val / totalSeats) * 100)
    .map((val) => parseFloat(val.toFixed(precision)));
}
