// 动画进度全局变量
declare const process: number;

/**
 * 图表数据点接口
 */
export interface DataPoint {
  x: number;
  y: number;
  color?: string;
  value?: number;
  width?: number;
  height?: number;
  r?: number; // 气泡图半径
  t?: string; // 气泡图文本
}

/**
 * 蜡烛图数据点
 */
export interface CandleDataPoint {
  x: number;
  y: number;
}

/**
 * 堆叠数据点（包含 y0 位置）
 */
export interface StackDataPoint extends DataPoint {
  y0: number;
}

/**
 * 条形堆叠数据点（包含 x0 位置）
 */
export interface BarStackDataPoint {
  color?: string;
  y: number;
  height: number;
  x: number;
  x0: number;
}

/**
 * 山丘图数据点（包含宽度和值）
 */
export interface MountDataPoint extends DataPoint {
  value: number;
  width: number;
}

/**
 * 图表配置接口
 */
export interface ChartOptions {
  type: string;
  categories?: string[];
  xAxis?: {
    boundaryGap?: string;
    itemcount?: number;
    [key: string]: any;
  };
  area: [number, number, number, number];
  width: number;
  height: number;
  pix?: number;
  enableScroll?: boolean;
  extra?: {
    mix?: {
      column?: {
        seriesGap?: number;
        categoryGap?: number;
        width?: number;
      };
    };
    column?: {
      seriesGap?: number;
      categoryGap?: number;
      width?: number;
    };
    bar?: {
      seriesGap?: number;
      categoryGap?: number;
      width?: number;
    };
    mount?: {
      widthRatio?: number;
    };
    radar?: {
      max?: number;
    };
    [key: string]: any;
  };
  chartData?: {
    xAxisData?: {
      ranges?: number[][];
    };
    [key: string]: any;
  };
  [key: string]: any;
}

/**
 * uCharts 配置接口
 */
export interface UChartsConfig {
  version: string;
  color: string[];
  [key: string]: any;
}

/**
 * 堆叠图系列项
 */
export interface SeriesItem {
  data: (number | null)[];
  color?: string;
  [key: string]: any;
}

/**
 * 折线动画选项
 */
export interface LineOption {
  animation?: string;
}

/**
 * 山丘图配置选项
 */
export interface MountOption {
  widthRatio?: number;
}

/**
 * 获取蜡烛图（K线图）数据点
 * @param data - 蜡烛图数据数组
 * @param minRange - 最小范围值
 * @param maxRange - 最大范围值
 * @param xAxisPoints - X轴点数组
 * @param eachSpacing - 每个点之间的间距
 * @param opts - 图表配置
 * @param config - uCharts配置
 * @returns 蜡烛图数据点数组
 */
export function getCandleDataPoints(
  data: (number | { value?: number })[][],
  minRange: number,
  maxRange: number,
  xAxisPoints: number[],
  eachSpacing: number,
  opts: ChartOptions,
  config: UChartsConfig
): (CandleDataPoint[] | null)[] {
  let points: (CandleDataPoint[] | null)[] = [];
  let validHeight = opts.height! - opts.area[0] - opts.area[2];
  data.forEach(function(item, index) {
    if (item === null) {
      points.push(null);
    } else {
      let cPoints: CandleDataPoint[] = [];
      item.forEach(function(items, indexs) {
        let point: CandleDataPoint = { x: 0, y: 0 };
        point.x = xAxisPoints[index] + Math.round(eachSpacing / 2);
        let value = typeof items === 'object' && items.value !== undefined ? items.value : items;
        let height = validHeight * ((value as number) - minRange) / (maxRange - minRange);
        height *= process;
        point.y = opts.height! - Math.round(height) - opts.area[2];
        cPoints.push(point);
      });
      points.push(cPoints);
    }
  });
  return points;
}

/**
 * 获取散点图和气泡图数据点
 * @param data - 数据数组
 * @param minRange - 最小范围值
 * @param maxRange - 最大范围值
 * @param xAxisPoints - X轴点数组
 * @param eachSpacing - 每个点之间的间距
 * @param opts - 图表配置
 * @param config - uCharts配置
 * @param process - 动画进度（默认为1）
 * @returns 数据点数组
 */
export function getDataPoints(
  data: (number | DataPoint | null)[],
  minRange: number,
  maxRange: number,
  xAxisPoints: number[],
  eachSpacing: number,
  opts: ChartOptions,
  config: UChartsConfig,
  process = 1
): (DataPoint | null)[] {
  let boundaryGap = 'center';
  if (opts.type == 'line' || opts.type == 'area' || opts.type == 'scatter' || opts.type == 'bubble' ) {
    boundaryGap = opts.xAxis?.boundaryGap || 'center';
  }
  let points: (DataPoint | null)[] = [];
  let validHeight = opts.height - opts.area[0] - opts.area[2];
  let validWidth = opts.width - opts.area[1] - opts.area[3];
  data.forEach(function(item, index) {
    if (item === null) {
      points.push(null);
    } else {
      let point: DataPoint = { x: 0, y: 0 };
      if (typeof item === 'object' && item !== null) {
        point.color = item.color;
      }
      point.x = xAxisPoints[index];
      let value: any = item;
      if (typeof item === 'object' && item !== null) {
        if (Array.isArray(item)) {
          const ranges = opts.chartData?.xAxisData?.ranges;
          if (ranges && ranges.length > 0) {
            const xranges = ranges as number[][];
            const allRanges: number[] = [...xranges[0], ...xranges[xranges.length - 1]];
            const xminRange = allRanges[0];
            const xmaxRange = allRanges[allRanges.length - 1];
            value = item[1];
            point.x = opts.area[3] + validWidth * (item[0] - xminRange) / (xmaxRange - xminRange);
          }
          if(opts.type == 'bubble'){
            point.r = item[2] as number | undefined;
            point.t = item[3] as string | undefined;
          }
        } else {
          value = item.value;
        }
      }
      if (boundaryGap == 'center') {
        point.x += eachSpacing / 2;
      }
      let height = validHeight * (value - minRange) / (maxRange - minRange);
      height *= process;
      point.y = opts.height - height - opts.area[2];
      points.push(point);
    }
  });
  return points;
}

/**
 * 获取折线图和面积图数据点
 * @param data - 数据数组
 * @param minRange - 最小范围值
 * @param maxRange - 最大范围值
 * @param xAxisPoints - X轴点数组
 * @param eachSpacing - 每个点之间的间距
 * @param opts - 图表配置
 * @param config - uCharts配置
 * @param lineOption - 折线动画选项
 * @param process - 动画进度（默认为1）
 * @returns 数据点数组
 */
export function getLineDataPoints(
  data: (number | DataPoint | null)[],
  minRange: number,
  maxRange: number,
  xAxisPoints: number[],
  eachSpacing: number,
  opts: ChartOptions,
  config: UChartsConfig,
  lineOption: LineOption,
  process = 1
): (DataPoint | null)[] {
  let boundaryGap = opts.xAxis?.boundaryGap || 'center';
  let points: (DataPoint | null)[] = [];
  let validHeight = opts.height - opts.area[0] - opts.area[2];
  let validWidth = opts.width - opts.area[1] - opts.area[3];
  data.forEach(function(item, index) {
    if (item === null) {
      points.push(null);
    } else {
      let point: DataPoint = { x: 0, y: 0 };
      if (typeof item === 'object' && item !== null) {
        point.color = item.color;
      }
      if(lineOption.animation == 'vertical'){
        point.x = xAxisPoints[index];
        let value: any = item;
        if (typeof item === 'object' && item !== null) {
          if (Array.isArray(item)) {
            const ranges = opts.chartData?.xAxisData?.ranges;
            if (ranges && ranges.length > 0) {
              const xranges = ranges as number[][];
              const allRanges: number[] = [...xranges[0], ...xranges[xranges.length - 1]];
              const xminRange = allRanges[0];
              const xmaxRange = allRanges[allRanges.length - 1];
              value = item[1];
              point.x = opts.area[3] + validWidth * (item[0] - xminRange) / (xmaxRange - xminRange);
            }
          } else {
            value = item.value;
          }
        }
        if (boundaryGap == 'center') {
          point.x += eachSpacing / 2;
        }
        let height = validHeight * (value - minRange) / (maxRange - minRange);
        height *= process;
        point.y = opts.height - height - opts.area[2];
        points.push(point);
      }else{
        point.x = xAxisPoints[0] + eachSpacing * index * process;
        let value: any = item;
        if (boundaryGap == 'center') {
          point.x += eachSpacing / 2;
        }
        let height = validHeight * (value - minRange) / (maxRange - minRange);
        point.y = opts.height - height - opts.area[2];
        points.push(point);
      }
    }
  });
  return points;
}

/**
 * 获取柱状图数据点
 * @param data - 数据数组
 * @param minRange - 最小范围值
 * @param maxRange - 最大范围值
 * @param xAxisPoints - X轴点数组
 * @param eachSpacing - 每个点之间的间距
 * @param opts - 图表配置
 * @param config - uCharts配置
 * @param zeroPoints - 零点（未使用，保留用于兼容性）
 * @param process - 动画进度（默认为1）
 * @returns 数据点数组
 */
export function getColumnDataPoints(
  data: (number | DataPoint | null)[],
  minRange: number,
  maxRange: number,
  xAxisPoints: number[],
  eachSpacing: number,
  opts: ChartOptions,
  config: UChartsConfig,
  zeroPoints: number[],
  process = 1
): (DataPoint | null)[] {
  let points: (DataPoint | null)[] = [];
  let validHeight = opts.height - opts.area[0] - opts.area[2];
  let validWidth = opts.width - opts.area[1] - opts.area[3];

  data.forEach(function(item, index) {
    if (item === null) {
      points.push(null);
    } else {
      let point: DataPoint = { x: 0, y: 0 };
      if (typeof item === 'object' && item !== null) {
        point.color = item.color;
      }
      point.x = xAxisPoints[index];
      let value: any = item;
      if (typeof item === 'object' && item !== null) {
        if (Array.isArray(item)) {
          const ranges = opts.chartData?.xAxisData?.ranges;
          if (ranges && ranges.length > 0) {
            const xranges = ranges as number[][];
            const allRanges: number[] = [...xranges[0], ...xranges[xranges.length - 1]];
            const xminRange = allRanges[0];
            const xmaxRange = allRanges[allRanges.length - 1];
            value = item[1];
            point.x = opts.area[3] + validWidth * (item[0] - xminRange) / (xmaxRange - xminRange);
          }
        } else {
          value = item.value;
        }
      }
      point.x += eachSpacing / 2;
      let height = validHeight * (value * process - minRange) / (maxRange - minRange);
      point.y = opts.height - height - opts.area[2];
      points.push(point);
    }
  });

  return points;
}

/**
 * 获取山丘图数据点
 * @param series - 系列数据数组
 * @param minRange - 最小范围值
 * @param maxRange - 最大范围值
 * @param xAxisPoints - X轴点数组
 * @param eachSpacing - 每个点之间的间距
 * @param opts - 图表配置
 * @param mountOption - 山丘图配置选项
 * @param zeroPoints - 零点（未使用，保留用于兼容性）
 * @returns 山丘图数据点数组
 */
export function getMountDataPoints(
  series: { data: number; color?: string }[],
  minRange: number,
  maxRange: number,
  xAxisPoints: number[],
  eachSpacing: number,
  opts: ChartOptions,
  mountOption: MountOption,
  zeroPoints: number[],
  process = 1
): (MountDataPoint | null)[] {
  let points: (MountDataPoint | null)[] = [];
  let validHeight = opts.height - opts.area[0] - opts.area[2];
  let validWidth = opts.width - opts.area[1] - opts.area[3];
  let mountWidth = eachSpacing * (mountOption.widthRatio || 1);
  series.forEach(function(item, index) {
    if (item === null) {
      points.push(null);
    } else {
      let point: MountDataPoint = { x: 0, y: 0, value: 0, width: 0 };
      point.color = item.color;
      point.x = xAxisPoints[index];
      point.x += eachSpacing / 2;
      let value = item.data;
      let height = validHeight * (value * process - minRange) / (maxRange - minRange);
      point.y = opts.height - height - opts.area[2];
      point.value = value;
      point.width = mountWidth;
      points.push(point);
    }
  });
  return points;
}

/**
 * 获取条形图数据点
 * @param data - 数据数组
 * @param minRange - 最小范围值
 * @param maxRange - 最大范围值
 * @param yAxisPoints - Y轴点数组
 * @param eachSpacing - 每个点之间的间距
 * @param opts - 图表配置
 * @param config - uCharts配置
 * @returns 数据点数组
 */
export function getBarDataPoints(
  data: (number | DataPoint | null)[],
  minRange: number,
  maxRange: number,
  yAxisPoints: number[],
  eachSpacing: number,
  opts: ChartOptions,
  config: UChartsConfig,
  process = 1
): DataPoint[] {
  let points: DataPoint[] = [];
  let validHeight = opts.height - opts.area[0] - opts.area[2];
  let validWidth = opts.width - opts.area[1] - opts.area[3];
  data.forEach(function(item, index) {
    if (item === null) {
      points.push({ x: 0, y: 0 });
    } else {
      let point: DataPoint = { x: 0, y: 0 };
      if (typeof item === 'object' && item !== null) {
        point.color = item.color;
      }
      point.y = yAxisPoints[index];
      let value: any = item;
      if (typeof item === 'object' && item !== null) {
        value = item.value;
      }
      let height = validWidth * (value - minRange) / (maxRange - minRange);
      height *= process;
      if ('height' in point) {
        (point as any).height = height;
      }
      if ('value' in point) {
        point.value = value;
      }
      point.x = height + opts.area[3];
      points.push(point);
    }
  });
  return points;
}

/**
 * 获取堆叠图数据点（用于柱状图/折线图堆叠）
 * @param data - 数据数组
 * @param minRange - 最小范围值
 * @param maxRange - 最大范围值
 * @param xAxisPoints - X轴点数组
 * @param eachSpacing - 每个点之间的间距
 * @param opts - 图表配置
 * @param config - uCharts配置
 * @param seriesIndex - 当前系列索引
 * @param stackSeries - 所有堆叠系列数据
 * @returns 堆叠数据点数组
 */
export function getStackDataPoints(
  data: (number | DataPoint | null)[],
  minRange: number,
  maxRange: number,
  xAxisPoints: number[],
  eachSpacing: number,
  opts: ChartOptions,
  config: UChartsConfig,
  seriesIndex: number,
  stackSeries: SeriesItem[],
  process = 1
): (StackDataPoint | null)[] {
  let points: (StackDataPoint | null)[] = [];
  let validHeight = opts.height - opts.area[0] - opts.area[2];
  data.forEach(function(item, index) {
    if (item === null) {
      points.push(null);
    } else {
      let point: StackDataPoint = { x: 0, y: 0, y0: 0 };
      if (typeof item === 'object' && item !== null) {
        point.color = item.color;
      }
      point.x = xAxisPoints[index] + Math.round(eachSpacing / 2);

      let height: number, height0: number;
      if (seriesIndex > 0) {
        let value = 0;
        for (let i = 0; i <= seriesIndex; i++) {
          value += stackSeries[i].data[index] || 0;
        }
        let value0 = value - (typeof item === 'object' && item !== null ? item.value || 0 : item);
        height = validHeight * (value - minRange) / (maxRange - minRange);
        height0 = validHeight * (value0 - minRange) / (maxRange - minRange);
      } else {
        let value = typeof item === 'object' && item !== null ? item.value || 0 : item;
        height = validHeight * (value - minRange) / (maxRange - minRange);
        height0 = 0;
      }
      let heightc = height0;
      height *= process;
      heightc *= process;
      point.y = opts.height - Math.round(height) - opts.area[2];
      point.y0 = opts.height - Math.round(heightc) - opts.area[2];
      points.push(point);
    }
  });
  return points;
}

/**
 * 获取条形堆叠图数据点
 * @param data - 数据数组
 * @param minRange - 最小范围值
 * @param maxRange - 最大范围值
 * @param yAxisPoints - Y轴点数组
 * @param eachSpacing - 每个点之间的间距
 * @param opts - 图表配置
 * @param config - uCharts配置
 * @param seriesIndex - 当前系列索引
 * @param stackSeries - 所有堆叠系列数据
 * @returns 条形堆叠数据点数组
 */
export function getBarStackDataPoints(
  data: (number | DataPoint | null)[],
  minRange: number,
  maxRange: number,
  yAxisPoints: number[],
  eachSpacing: number,
  opts: ChartOptions,
  config: UChartsConfig,
  seriesIndex: number,
  stackSeries: SeriesItem[],
  process = 1
): (BarStackDataPoint | null)[] {
  let points: (BarStackDataPoint | null)[] = [];
  let validHeight = opts.width - opts.area[1] - opts.area[3];
  data.forEach(function(item, index) {
    if (item === null) {
      points.push(null);
    } else {
      let point: BarStackDataPoint = { x: 0, x0: 0, y: 0, height: 0 };
      if (typeof item === 'object' && item !== null) {
        point.color = item.color;
      }
      point.y = yAxisPoints[index];
      let height: number, height0: number;
      if (seriesIndex > 0) {
        let value = 0;
        for (let i = 0; i <= seriesIndex; i++) {
          value += stackSeries[i].data[index] || 0;
        }
        let value0 = value - (typeof item === 'object' && item !== null ? item.value || 0 : item);
        height = validHeight * (value - minRange) / (maxRange - minRange);
        height0 = validHeight * (value0 - minRange) / (maxRange - minRange);
      } else {
        let value = typeof item === 'object' && item !== null ? item.value || 0 : item;
        height = validHeight * (value - minRange) / (maxRange - minRange);
        height0 = 0;
      }
      let heightc = height0;
      height *= process;
      heightc *= process;
      point.height = height - heightc;
      point.x = opts.area[3] + height;
      point.x0 = opts.area[3] + heightc;
      points.push(point);
    }
  });
  return points;
}
