/**
 * K线图绘制函数
 *
 * 从 u-charts 核心库搬迁的K线图绘制相关函数
 */

// @ts-nocheck - 由于从 u-charts 搬迁，类型系统不兼容，暂时禁用类型检查

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

import type { ChartOptions, UChartsConfig, SeriesItem } from '../data-processing/series-calculator';
import { getDataPoints, getCandleDataPoints } from '../charts-data/basic-charts';
import { splitPoints, createCurveControlPoints } from '../utils/misc';
import { assign } from '../config';

export type CanvasContext = any;

export interface Point {
  x: number;
  y: number;
}

export interface CandleOption {
  color: {
    upLine: string;
    upFill: string;
    downLine: string;
    downFill: string;
  };
  average: {
    show: boolean;
    name: string[];
    day: number[];
    color: string[];
  };
}

export function drawCandleDataPoints(
  series: SeriesItem[],
  seriesMA: SeriesItem[],
  opts: ChartOptions,
  config: UChartsConfig,
  context: CanvasContext
): { xAxisPoints: number[]; calPoints: any[]; eachSpacing: number } {
  let candleOption = assign({}, {
    color: {
      upLine: '#f04864',
      upFill: '#f04864',
      downLine: '#2fc25b',
      downFill: '#2fc25b'
    },
    average: {
      show: false,
      name: [],
      day: [],
      color: config.color
    }
  }, opts.extra?.candle || {}) as CandleOption;
  opts.extra = opts.extra || {};
  opts.extra.candle = candleOption;

  let xAxisData = opts.chartData!.xAxisData;
  let xAxisPoints = xAxisData.xAxisPoints;
  let eachSpacing = xAxisData.eachSpacing;
  let calPoints: any[] = [];

  context.save();
  let leftNum = -2;
  let rightNum = xAxisPoints.length + 2;
  let leftSpace = 0;
  let rightSpace = opts.width! + eachSpacing;
  if (opts._scrollDistance_ && opts._scrollDistance_ !== 0 && opts.enableScroll === true) {
    context.translate(opts._scrollDistance_, 0);
    leftNum = Math.floor(-opts._scrollDistance_ / eachSpacing) - 2;
    rightNum = leftNum + (opts.xAxis?.itemCount || 0) + 4;
    leftSpace = -opts._scrollDistance_ - eachSpacing * 2 + opts.area![3];
    rightSpace = leftSpace + ((opts.xAxis?.itemCount || 0) + 4) * eachSpacing;
  }

  // 画均线
  if (candleOption.average.show || seriesMA) {
    seriesMA.forEach(function(eachSeries, seriesIndex) {
      let ranges, minRange, maxRange;
      ranges = [].concat(opts.chartData!.yAxisData!.ranges[(eachSeries.index || 0) as number]);
      minRange = ranges.pop();
      maxRange = ranges.shift();
      let data = eachSeries.data;
      let points = getDataPoints(data as any, minRange!, maxRange!, xAxisPoints, eachSpacing, opts, config);
      let splitPointList = splitPoints(points, eachSeries as any);
      for (let i = 0; i < splitPointList.length; i++) {
        let points = splitPointList[i];
        context.beginPath();
        context.setStrokeStyle(eachSeries.color);
        context.setLineWidth(1);
        if (points.length === 1) {
          context.moveTo(points[0].x, points[0].y);
          context.arc(points[0].x, points[0].y, 1, 0, 2 * Math.PI);
        } else {
          context.moveTo(points[0].x, points[0].y);
          let startPoint = 0;
          for (let j = 0; j < points.length; j++) {
            let item = points[j];
            if (startPoint == 0 && item.x > leftSpace) {
              context.moveTo(item.x, item.y);
              startPoint = 1;
            }
            if (j > 0 && item.x > leftSpace && item.x < rightSpace) {
              let ctrlPoint = createCurveControlPoints(points, j - 1);
              context.bezierCurveTo(ctrlPoint.ctrA.x, ctrlPoint.ctrA.y, ctrlPoint.ctrB.x, ctrlPoint.ctrB.y, item.x,
                item.y);
            }
          }
          context.moveTo(points[0].x, points[0].y);
        }
        context.closePath();
        context.stroke();
      }
    });
  }

  // 画K线
  series.forEach(function(eachSeries, seriesIndex) {
    let ranges, minRange, maxRange;
    ranges = [].concat(opts.chartData!.yAxisData!.ranges[(eachSeries.index || 0) as number]);
    minRange = ranges.pop();
    maxRange = ranges.shift();
    let data = eachSeries.data;
    let points = getCandleDataPoints(data as any, minRange!, maxRange!, xAxisPoints, eachSpacing, opts, config);
    calPoints.push(points);
    let splitPointList = splitPoints(points, eachSeries as any);
    for (let i = 0; i < splitPointList[0].length; i++) {
      if (i > leftNum && i < rightNum) {
        let item = splitPointList[0][i];
        context.beginPath();
        // 如果上涨
        if ((data as any)![i]![1] - (data as any)![i]![0] > 0) {
          context.setStrokeStyle(candleOption.color.upLine);
          context.setFillStyle(candleOption.color.upFill);
          context.setLineWidth(1 * opts.pix);
          context.moveTo(item[3].x, item[3].y); // 顶点
          context.lineTo(item[1].x, item[1].y); // 收盘中间点
          context.lineTo(item[1].x - eachSpacing / 4, item[1].y); // 收盘左侧点
          context.lineTo(item[0].x - eachSpacing / 4, item[0].y); // 开盘左侧点
          context.lineTo(item[0].x, item[0].y); // 开盘中间点
          context.lineTo(item[2].x, item[2].y); // 底点
          context.lineTo(item[0].x, item[0].y); // 开盘中间点
          context.lineTo(item[0].x + eachSpacing / 4, item[0].y); // 开盘右侧点
          context.lineTo(item[1].x + eachSpacing / 4, item[1].y); // 收盘右侧点
          context.lineTo(item[1].x, item[1].y); // 收盘中间点
          context.moveTo(item[3].x, item[3].y); // 顶点
        } else {
          context.setStrokeStyle(candleOption.color.downLine);
          context.setFillStyle(candleOption.color.downFill);
          context.setLineWidth(1 * opts.pix);
          context.moveTo(item[3].x, item[3].y); // 顶点
          context.lineTo(item[0].x, item[0].y); // 开盘中间点
          context.lineTo(item[0].x - eachSpacing / 4, item[0].y); // 开盘左侧点
          context.lineTo(item[1].x - eachSpacing / 4, item[1].y); // 收盘左侧点
          context.lineTo(item[1].x, item[1].y); // 收盘中间点
          context.lineTo(item[2].x, item[2].y); // 底点
          context.lineTo(item[1].x, item[1].y); // 收盘中间点
          context.lineTo(item[1].x + eachSpacing / 4, item[1].y); // 收盘右侧点
          context.lineTo(item[0].x + eachSpacing / 4, item[0].y); // 开盘右侧点
          context.lineTo(item[0].x, item[0].y); // 开盘中间点
          context.moveTo(item[3].x, item[3].y); // 顶点
        }
        context.closePath();
        context.fill();
        context.stroke();
      }
    }
  });

  context.restore();

  return {
    xAxisPoints: xAxisPoints,
    calPoints: calPoints,
    eachSpacing: eachSpacing
  };
}
