<template>
  <div class="flow-ruler-container">
    <div class="ruler-x">
      <canvas ref="rulerXCanvas" class="ruler-canvas"></canvas>
    </div>
    <div class="main-content">
      <div class="ruler-y">
        <canvas ref="rulerYCanvas" class="ruler-canvas"></canvas>
      </div>
      <slot />
    </div>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue';
import { useVueFlow } from '@vue-flow/core';

const rulerXCanvas = ref(null);
const rulerYCanvas = ref(null);
const { viewport } = useVueFlow();

let animationFrameId = null;
let lastRenderTime = 0;
const FRAME_INTERVAL = 1000 / 60;

const getNiceStep = (target) => {
  const steps = [1, 2, 5, 10, 20, 25, 50, 100, 200, 500, 1000];
  return steps.find(s => s * viewport.value.zoom >= target) || 1000;
};

const drawRulers = () => {
  const scale = viewport.value.zoom;
  const offsetX = viewport.value.x;
  const offsetY = viewport.value.y;

  const step = getNiceStep(10);
  const bigStep = step * 10;
  const leftOffset = 30;
  const rulerSize = 30;

  const xCanvas = rulerXCanvas.value;
  const xCtx = xCanvas.getContext('2d');
  xCanvas.width = xCanvas.offsetWidth * window.devicePixelRatio;
  xCanvas.height = xCanvas.offsetHeight * window.devicePixelRatio;
  xCtx.scale(window.devicePixelRatio, window.devicePixelRatio);
  xCtx.clearRect(0, 0, xCanvas.offsetWidth, xCanvas.offsetHeight);

  xCtx.fillStyle = '#999';
  xCtx.font = '10px sans-serif';

  const canvasWidth = xCanvas.offsetWidth;
  const startWorldX = Math.floor((-offsetX - leftOffset) / scale / step) * step;
  const endWorldX = (-offsetX + canvasWidth) / scale;

  for (let worldX = startWorldX; worldX < endWorldX; worldX += step) {
    const screenX = worldX * scale + offsetX + leftOffset;
    xCtx.beginPath();
    if (Math.round(worldX) % bigStep === 0) {
      xCtx.strokeStyle = '#fff';
      xCtx.moveTo(screenX, rulerSize - 20);
      xCtx.lineTo(screenX, rulerSize);
      xCtx.stroke();
      xCtx.fillStyle = '#ccc';
      xCtx.fillText(Math.round(worldX).toString(), screenX + 2, 10);
    } else {
      xCtx.strokeStyle = '#666';
      xCtx.moveTo(screenX, rulerSize - 10);
      xCtx.lineTo(screenX, rulerSize);
      xCtx.stroke();
    }
  }

  const yCanvas = rulerYCanvas.value;
  const yCtx = yCanvas.getContext('2d');
  yCanvas.width = yCanvas.offsetWidth * window.devicePixelRatio;
  yCanvas.height = yCanvas.offsetHeight * window.devicePixelRatio;
  yCtx.scale(window.devicePixelRatio, window.devicePixelRatio);
  yCtx.clearRect(0, 0, yCanvas.offsetWidth, yCanvas.offsetHeight);

  yCtx.fillStyle = '#999';
  yCtx.font = '10px sans-serif';

  const canvasHeight = yCanvas.offsetHeight;
  const startWorldY = Math.floor((-offsetY) / scale / step) * step;
  const endWorldY = (-offsetY + canvasHeight) / scale;

  for (let worldY = startWorldY; worldY < endWorldY; worldY += step) {
    const screenY = worldY * scale + offsetY;
    yCtx.beginPath();
    if (Math.round(worldY) % bigStep === 0) {
      yCtx.strokeStyle = '#fff';
      yCtx.save();
      yCtx.translate(rulerSize - 2, screenY + 5);
      yCtx.rotate(-Math.PI / 2);
      yCtx.fillStyle = '#ccc';
      yCtx.fillText(Math.round(worldY).toString(), 0, 0);
      yCtx.restore();

      yCtx.moveTo(rulerSize - 20, screenY);
      yCtx.lineTo(rulerSize, screenY);
      yCtx.stroke();
    } else {
      yCtx.strokeStyle = '#666';
      yCtx.moveTo(rulerSize - 10, screenY);
      yCtx.lineTo(rulerSize, screenY);
      yCtx.stroke();
    }
  }
};

const renderLoop = (time) => {
  if (time - lastRenderTime >= FRAME_INTERVAL) {
    drawRulers();
    lastRenderTime = time;
  }
  animationFrameId = requestAnimationFrame(renderLoop);
};

onMounted(() => {
  animationFrameId = requestAnimationFrame(renderLoop);
});
</script>

<style scoped>
.flow-ruler-container {
  position: relative;
  width: 100%;
  height: 100%;
  overflow: hidden;
}

.ruler-x {
  height: 30px;
  background: #1F2122;
  border-bottom: 1px solid #444;
  overflow: hidden;
}

.ruler-y {
  width: 30px;
  background: #1F2122;
  border-right: 1px solid #444;
  height: 100%;
  overflow: hidden;
}

.main-content {
  display: flex;
  height: calc(100% - 30px);
}

.ruler-canvas {
  width: 100%;
  height: 100%;
  display: block;
}
</style>
