// 其他工具函数
// 来源: u-charts.ts

/**
 * H5 事件接口
 */
export interface H5Event {
  offsetX: number;
  offsetY: number;
  mp: {
    changedTouches: Array<{ x: number; y: number }>;
  };
}

/**
 * 触摸点接口
 */
export interface TouchPoint {
  x?: number;
  y?: number;
  clientX?: number;
  clientY?: number;
  pageX?: number;
  pageY?: number;
}

/**
 * 图表选项接口（用于 getTouches）
 */
export interface ChartOptions {
  rotate?: boolean;
  height: number;
  pix: number;
  width?: number;
}

/**
 * DOM 事件接口
 */
export interface DOMEvent {
  currentTarget?: {
    offsetTop?: number;
  };
}

/**
 * 兼容 H5 点击事件
 * 将 H5 的 offsetX/offsetY 转换为小程序格式的 changedTouches
 * @param e - H5 事件对象
 * @returns 转换后的事件对象
 */
export function getH5Offset(e: { offsetX: number; offsetY: number }): H5Event {
  (e as H5Event).mp = {
    changedTouches: []
  };
  (e as H5Event).mp.changedTouches.push({
    x: e.offsetX,
    y: e.offsetY
  });
  return e as H5Event;
}

/**
 * 曲线控制点接口
 */
export interface CurveControlPoints {
  ctrA: {
    x: number | null;
    y: number | null;
  };
  ctrB: {
    x: number | null;
    y: number | null;
  };
}

/**
 * 点数组接口（用于 createCurveControlPoints）
 */
export interface PointArray extends Array<{ x: number; y: number }> {}

/**
 * 创建曲线控制点
 * 用于绘制平滑曲线（贝塞尔曲线）
 * @param points - 点数组
 * @param i - 当前点索引
 * @returns 曲线控制点
 */
export function createCurveControlPoints(points: PointArray, i: number): CurveControlPoints {
  function isNotMiddlePoint(pts: PointArray, idx: number): boolean {
    if (pts[idx - 1] && pts[idx + 1]) {
      return pts[idx].y >= Math.max(pts[idx - 1].y, pts[idx + 1].y) || pts[idx].y <= Math.min(pts[idx - 1].y,
        pts[idx + 1].y);
    } else {
      return false;
    }
  }
  function isNotMiddlePointX(pts: PointArray, idx: number): boolean {
    if (pts[idx - 1] && pts[idx + 1]) {
      return pts[idx].x >= Math.max(pts[idx - 1].x, pts[idx + 1].x) || pts[idx].x <= Math.min(pts[idx - 1].x,
        pts[idx + 1].x);
    } else {
      return false;
    }
  }
  let a = 0.2;
  let b = 0.2;
  let pAx: number | null = null;
  let pAy: number | null = null;
  let pBx: number | null = null;
  let pBy: number | null = null;
  if (i < 1) {
    pAx = points[0].x + (points[1].x - points[0].x) * a;
    pAy = points[0].y + (points[1].y - points[0].y) * a;
  } else {
    pAx = points[i].x + (points[i + 1].x - points[i - 1].x) * a;
    pAy = points[i].y + (points[i + 1].y - points[i - 1].y) * a;
  }

  if (i > points.length - 3) {
    let last = points.length - 1;
    pBx = points[last].x - (points[last].x - points[last - 1].x) * b;
    pBy = points[last].y - (points[last].y - points[last - 1].y) * b;
  } else {
    pBx = points[i + 1].x - (points[i + 2].x - points[i].x) * b;
    pBy = points[i + 1].y - (points[i + 2].y - points[i].y) * b;
  }
  if (isNotMiddlePoint(points, i + 1)) {
    pBy = points[i + 1].y;
  }
  if (isNotMiddlePoint(points, i)) {
    pAy = points[i].y;
  }
  if (isNotMiddlePointX(points, i + 1)) {
    pBx = points[i + 1].x;
  }
  if (isNotMiddlePointX(points, i)) {
    pAx = points[i].x;
  }
  if (pAy >= Math.max(points[i].y, points[i + 1].y) || pAy <= Math.min(points[i].y, points[i + 1].y)) {
    pAy = points[i].y;
  }
  if (pBy >= Math.max(points[i].y, points[i + 1].y) || pBy <= Math.min(points[i].y, points[i + 1].y)) {
    pBy = points[i + 1].y;
  }
  if (pAx >= Math.max(points[i].x, points[i + 1].x) || pAx <= Math.min(points[i].x, points[i + 1].x)) {
    pAx = points[i].x;
  }
  if (pBx >= Math.max(points[i].x, points[i + 1].x) || pBx <= Math.min(points[i].x, points[i + 1].x)) {
    pBx = points[i + 1].x;
  }
  return {
    ctrA: {
      x: pAx,
      y: pAy
    },
    ctrB: {
      x: pBx,
      y: pBy
    }
  };
}

/**
 * 分割数据点（处理 null 值）
 * 用于折线图等图表的断点处理
 * @param points - 数据点数组
 * @param eachSeries - 系列配置（包含 connectNulls 属性）
 * @returns 分割后的数据点数组
 */
export function splitPoints<T>(points: (T | null)[], eachSeries: { connectNulls?: boolean }): T[][] {
  const newPoints: T[][] = [];
  const items: T[] = [];
  points.forEach(function(item, index) {
    if (eachSeries.connectNulls) {
      if (item !== null) {
        items.push(item);
      }
    } else {
      if (item !== null) {
        items.push(item);
      } else {
        if (items.length) {
          newPoints.push(items);
        }
        items.length = 0;
      }
    }
  });
  if (items.length) {
    newPoints.push(items);
  }
  return newPoints;
}

/**
 * 获取触摸点坐标
 * 支持小程序和 H5 两种格式
 * @param touches - 触摸点数组或单个触摸点
 * @param opts - 图表选项
 * @param e - DOM 事件对象
 * @returns 触摸点坐标
 */
export function getTouches(
  touches: TouchPoint | TouchPoint[],
  opts: ChartOptions,
  e: DOMEvent
): TouchPoint {
  let x: number, y: number;
  const touch = Array.isArray(touches) ? touches[0] : touches;

  if (touch.clientX) {
    if (opts.rotate) {
      y = opts.height - touch.clientX! * opts.pix;
      x = (touch.pageY! - (e.currentTarget?.offsetTop || 0) - (opts.height / opts.pix / 2) * (opts.pix - 1)) * opts.pix;
    } else {
      x = touch.clientX! * opts.pix;
      y = (touch.pageY! - (e.currentTarget?.offsetTop || 0) - (opts.height / opts.pix / 2) * (opts.pix - 1)) * opts.pix;
    }
  } else {
    if (opts.rotate) {
      y = opts.height - touch.x! * opts.pix;
      x = touch.y! * opts.pix;
    } else {
      x = touch.x! * opts.pix;
      y = touch.y! * opts.pix;
    }
  }
  return {
    x: x,
    y: y
  };
}
