const positions: Record<string, AccountPosition> = {
    "BTCBUSD": {
      symbol: "BTCBUSD",
      quantity: 3,
      openPrice: 25690,
      amount: 150,
      openDate: "2023-01-01",
      side: "ask",
      apiKeyId: "2",
    },
  };

  useEffect(() => {
    if (!workerRef.current) return;
   workerRef.current.onmessage = (event: MessageEvent<UpdateCupEvent|OrderEvent>) => {
  if (event?.data?.type === "update_cup") {
animationFrameId = requestAnimationFrame(() => {
          const data = event.data as UpdateCupEvent;

          const context = canvasRef.current?.getContext("2d");
          const zoomedTickSize = data.priceStep * data.aggregation;

          if (context) {
            const rowsOnScreenCount = cupTools.getRowsCountOnScreen(
              canvasSize.height,
              cupOptions().cell.defaultHeight * dpiScale,
            );
            const realCellHeight = parseInt((canvasSize.height / rowsOnScreenCount).toFixed(0));

            if (data.rowsCount !== rowsOnScreenCount) {
              workerRef.current?.postMessage(JSON.stringify({type: "change_rows_count", value: rowsOnScreenCount}));
            }

            cupDrawer.clear(context, canvasSize);

            if (cupParams.rowCount !== rowsOnScreenCount
              || cupParams.cellHeight !== realCellHeight
              || cupParams.aggregation !== data.aggregation
            ) {
              dispatch(setCupParams({
                aggregation: data.aggregation,
                rowCount: rowsOnScreenCount,
                cellHeight: realCellHeight,
                pricePrecision: data.pricePrecision,
                priceStep: data.priceStep,
                quantityPrecision: data.quantityPrecision,
              }));
            }

            console.log(data.priceStep);

            if (data.camera === 0 && isLoaded) {
              setIsLoaded(false);
            }

            if (data.camera > 0 && !isLoaded) {
              setIsLoaded(true);
            }

            if (data.camera !== 0) {
              cupDrawer.draw(
                context,
                canvasSize,
                dpiScale,
                data.bestBidPrice,
                data.bestAskPrice,
                data.maxVolume,
                data.pricePrecision,
                data.quantityPrecision,
                data.priceStep,
                data.aggregation,
                rowsOnScreenCount,
                data.camera,
                realCellHeight,
                {
                  buy: parseInt((Math.floor(data.bestBidPrice / zoomedTickSize) * zoomedTickSize).toFixed(0)),
                  sell: parseInt((Math.ceil(data.bestAskPrice / zoomedTickSize) * zoomedTickSize).toFixed(0)),
                },
                darkMode,
                data.volumeAsDollars,
                data.cup,
                positions,
              );
            }
          }
        });
      }
    };

    return () => {
      if (null !== animationFrameId) {
        cancelAnimationFrame(animationFrameId);
      }
    };
  }, [workerRef.current, canvasSize, darkMode, dpiScale, isLoaded, quantity]);


const cupDrawer = {
  clear: (ctx: CanvasRenderingContext2D, size: CanvasSize) => {
    ctx.clearRect(0, 0, size.width, size.height);
  },
  draw: (
    ctx: CanvasRenderingContext2D,
    size: CanvasSize,
    dpiScale: number,
    bestBidPrice: number,
    bestAskPrice: number,
    maxVolume: number,
    pricePrecision: number,
    quantityPrecision: number,
    priceStep: number,
    zoom: number,
    rowCount: number,
    camera: number,
    cellHeight: number,
    zoomedBestMicroPrice: any,
    darkMode: boolean,
    volumeAsDollars: boolean,
    cup: {[key: number]: CupItem},
    positions: Record<string, AccountPosition>,
  ) => {
    const zoomedTickSize = priceStep * zoom;
    const startMicroPrice = camera + rowCount / 2 * zoomedTickSize - zoomedTickSize;
    const quantityDivider = Math.pow(10, quantityPrecision);
    const priceDivider = Math.pow(10, pricePrecision);

    for (let index = 0; index <= rowCount; index++) {
      const microPrice = startMicroPrice - index * zoomedTickSize;

      if (microPrice < 0) continue;

      const item = cup[microPrice] || {};
      let side = "undefined" !== typeof item?.bid
        ? "bid"
        : "undefined" !== typeof item?.ask ? "ask" : "";

      if ("" === side || (!item?.bid && !item.ask)) {
        side = (microPrice >= (zoomedBestMicroPrice?.buy || zoomedBestMicroPrice?.sell || 0) ? "ask" : "bid");
      }

      const yPosition = cellHeight * index;
      const quantity = volumeAsDollars
        ? ((side === "bid" ? item?.bid || 0 : item?.ask || 0) / quantityDivider) * (microPrice / priceDivider)
        : (side === "bid" ? item?.bid || 0 : item?.ask || 0) / quantityDivider;

      const isBestPrice = cupTools.isBestPrice(
        side,
        microPrice,
        zoomedBestMicroPrice,
      );

      if ((microPrice / zoomedTickSize) % 5 === 0) {
        ctx.beginPath();
        ctx.strokeStyle = darkMode ? "#232425" : "#dddedf";
        ctx.lineWidth = Math.max(1, dpiScale);
        ctx.moveTo(0, yPosition);
        ctx.lineTo(size.width, yPosition);
        ctx.stroke();
      }

      cupDrawer.drawCell(
        ctx,
        quantity,
        side,
        maxVolume,
        isBestPrice,
        yPosition,
        cellHeight,
        size.width,
        dpiScale,
        darkMode
      );

      if (isBestPrice) {
        cupDrawer.drawFill(
          ctx,
          quantity,
          side,
          maxVolume,
          yPosition,
          cellHeight,
          size.width,
          dpiScale,
          darkMode
        );
      }

      cupDrawer.drawPrice(
        ctx,
        cupTools.microPriceToReal(microPrice, pricePrecision),
        side,
        isBestPrice,
        yPosition,
        cellHeight,
        size.width,
        dpiScale,
        darkMode
      );

      cupDrawer.drawQuantity(
        ctx,
        cupTools.abbreviateNumber(quantity),
        side,
        isBestPrice,
        yPosition,
        cellHeight,
        size.width,
        dpiScale,
        darkMode
      );
    }
  },
  drawCell: (
    ctx: CanvasRenderingContext2D,
    quantity: number,
    side: string,
    maxVolume: number,
    isBestPrice: boolean,
    yPosition: number,
    cellHeight: number,
    fullWidth: number,
    dpiScale: number,
    darkMode: boolean,
  ) => {
    ctx.beginPath();
    ctx.strokeStyle = cupOptions(darkMode).border.color;
    ctx.lineWidth = cupOptions(darkMode).border.width;
    ctx.fillStyle = cupTools.getCellBackground(side, isBestPrice, darkMode);
    // @ts-ignore
    ctx.roundRect(
      0,
      yPosition,
      cupTools.getCellWidth(fullWidth, quantity, maxVolume, isBestPrice),
      cellHeight,
      cupOptions(darkMode).border.radius * dpiScale,
    );
    ctx.fill();
    ctx.stroke();
  },
  drawFill: (
    ctx: CanvasRenderingContext2D,
    quantity: number,
    side: string,
    maxVolume: number,
    yPosition: number,
    cellHeight: number,
    fullWidth: number,
    dpiScale: number,
    darkMode: boolean,
  ) => {
    const cornerRadius = cupOptions().border.radius * dpiScale;
    const x = 0;
    const y = yPosition;
    const height = cellHeight;
    const fillColor = side === "bid"
      ? cupOptions(darkMode).bestBuy.fillColor
      : cupOptions(darkMode).bestSell.fillColor;

    ctx.beginPath();
    ctx.rect(
      0,
      y + 1,
      cupTools.getCellWidth(fullWidth, quantity, maxVolume, false),
      height - 2,
    );

    ctx.fillStyle = fillColor;
    ctx.fill();

    ctx.fillStyle = darkMode ? "#191919" : "#fff";
    ctx.beginPath();
    ctx.moveTo(x, y + cornerRadius);
    ctx.arc(x + cornerRadius, y + cornerRadius, cornerRadius, Math.PI, Math.PI * 1.5);
    ctx.lineTo(x, y);
    ctx.closePath();
    ctx.fill();

    ctx.beginPath();
    ctx.moveTo(x + cornerRadius, y + height);
    ctx.arc(x + cornerRadius, y + height - cornerRadius, cornerRadius, Math.PI * 0.5, Math.PI);
    ctx.lineTo(x, y + height);
    ctx.closePath();
    ctx.fill();

    ctx.beginPath();
    ctx.moveTo(x + fullWidth - cornerRadius, y);
    ctx.arc(x + fullWidth - cornerRadius, y + cornerRadius, cornerRadius, Math.PI * 1.5, 0);
    ctx.lineTo(x + fullWidth, y);
    ctx.closePath();
    ctx.fill();

    ctx.beginPath();
    ctx.moveTo(x + fullWidth, y + height - cornerRadius);
    ctx.arc(x + fullWidth - cornerRadius, y + height - cornerRadius, cornerRadius, 0, Math.PI * 0.5);
    ctx.lineTo(x + fullWidth, y + height);
    ctx.closePath();
    ctx.fill();

    ctx.stroke();
  },
  drawPrice: (
    ctx: CanvasRenderingContext2D,
    price: string,
    side: string,
    isBestPrice: boolean,
    yPosition: number,
    cellHeight: number,
    fullWidth: number,
    dpiScale: number,
    darkMode: boolean,
  ) => {
    const {width: textWidth} = ctx.measureText(price);
    ctx.textBaseline = "middle";
    ctx.font = `${cupOptions().font.weight} ${cupOptions().font.sizePx * dpiScale}px ${cupOptions().font.family}`;
    ctx.fillStyle = cupTools.getPriceColor(side, isBestPrice, darkMode);
    ctx.fillText(
      price,
      fullWidth - cupOptions().cell.paddingX * dpiScale - textWidth,
      yPosition + cellHeight / 2,
    );
  },
  drawQuantity: (
    ctx: CanvasRenderingContext2D,
    quantity: string,
    side: string,
    isBestPrice: boolean,
    yPosition: number,
    cellHeight: number,
    fullWidth: number,
    dpiScale: number,
    darkMode: boolean,
  ) => {
    ctx.textBaseline = "middle";
    ctx.fillStyle = cupTools.getQuantityColor(side, isBestPrice, darkMode);
    ctx.fillText(
      quantity,
      cupOptions().cell.paddingX * dpiScale,
      yPosition + cellHeight / 2,
    );
  },
};

export default cupDrawer;

positions нужно отображать в виде полупрозрачного прямоугольника от цены входа до bestPrice.