import {GPU} from "gpu.js";
export interface CanvasSize {
  width: number;
  height: number;
}
const OrderFeed = ({workerRef, symbol, settings}: OrderFeedProps) => {
  const cupParams = useSelector((state: AppState) => state.cupSlice);
  const [dpiScale, setDpiScale] = useState(Math.ceil(window.devicePixelRatio));
  const [canvasSize, setCanvasSize] = useState<CanvasSize>({height: 0, width: 0});
  const containerRef = useRef<HTMLDivElement|null>(null);
  const canvasRef = useRef<HTMLCanvasElement|null>(null);

  const draw = (trades: TradeItem[], camera: number) => {
    if (null === canvasRef || !Array.isArray(trades)) return;

    const context = canvasRef.current?.getContext("webgl");

    if (context) {

      const gpu = new GPU({canvas: canvasRef, context});

      orderFeedDrawer.clear(context, canvasSize);
     orderFeedDrawer.drawLine(
        gpu,
        context,
        canvasSize,
        trades,
        camera,
        cupParams.aggregatedPriceStep,
        cupParams.cellHeight,
        cupParams.quantityDivider,
        !settings.minQuantity ? 0 : parseFloat(settings.minQuantity),
        dpiScale,
        theme,
      );
}
  };

  return <Box ref={containerRef} className={`${styles.canvasWrapper} scroll-block`}>
    <canvas
      ref={canvasRef}
      className={styles.canvas}
      width={canvasSize?.width}
      height={canvasSize?.height}
    />
  </Box>;
};

export default OrderFeed;


const clamp = (value: number, min: number, max: number): number => {
  return Math.min(Math.max(value, min), max);
};

const orderFeedDrawer = {
  clear: (ctx: WebGLRenderingContext, size: CanvasSize) => {
    ctx.clear(0);
  },
  drawLine: (
    gpu: GPU,
    ctx: WebGLRenderingContext,
    canvasSize: CanvasSize,
    trades: TradeItem[],
    camera: number,
    aggregatedPriceStep: number,
    cupCellHeight: number,
    quantityDivider: number,
    minQuantity: number,
    dpiScale: number,
    theme: Theme,
  ) => {
    const kernelFunction = gpu.createKernel(function(trades: TradeItem[], camera: number, aggregatedPriceStep: number, cupCellHeight: number, quantityDivider: number, minQuantity: number, dpiScale: number, startX: number, startY: number, halfCupCellHeight: number): { startX: number, startY: number, width: number } {
      const trade = trades[this.thread.y];
      const yModifier = (trade.price - (trade.price - (trade?.secondPrice || trade.price)) / 2 - camera) / aggregatedPriceStep * cupCellHeight + halfCupCellHeight;
      const width = 1.75 * clamp((trade.quantity / quantityDivider < minQuantity ? 0 : trade.radius), 5, 50) * dpiScale;

      return {
        startX: startX - width,
        startY: startY - yModifier,
        width: width,
      };
    }, {
      output: [trades.length],
    });

    const kernelResult = kernelFunction(trades, camera, aggregatedPriceStep, cupCellHeight, quantityDivider, minQuantity, dpiScale, startX, startY, halfCupCellHeight);

    // Преобразование результатов из ядра в массив данных
    const resultArray = kernelResult.map((item) => ({startX: item.startX, startY: item.startY, width: item.width}));

    ctx.beginPath();
    ctx.strokeStyle = orderFeedOptions(theme).line.color;
    ctx.lineWidth = (dpiScale) => 2 * dpiScale;

    resultArray.forEach((trade) => {
      ctx.lineTo(trade.startX - trade.width / 2, trade.startY);
    });

    ctx.stroke();
  },