<template>
  <div class="render-container">
    <div class="animation-controls" v-if="hasArrows">
      <button 
        type="button"
        class="btn-animate"
        @click="startAnimation"
        :disabled="isAnimating"
      >
        {{ isAnimating ? $t('courtDrawingRender.animationRunning') : $t('courtDrawingRender.startAnimation') }}
      </button>
    </div>
    <canvas
      ref="canvas"
      :width="config.canvas.width"
      :height="config.canvas.height"
      class="render-canvas"
    ></canvas>
  </div>
  
</template>

<script>
const COURT_RENDER_PALETTE = {
  table: '#315f43',
  frame: '#ffffff',
  frameBorder: '#102418',
  line: '#d9e4dd',
  net: '#ffffff',
  netBorder: '#102418',
  startSelected: '#c84c32',
  startMuted: '#8d948f',
  startMutedBorder: '#4d5650',
  arrowPrimary: '#c84c32',
  arrowSecondary: '#1f6a8a',
  arrowTertiary: '#4f7f32',
  arrowQuaternary: '#8a5a1f',
  markerFill: '#ffffff',
  markerStroke: '#102418',
  surface: '#eef3ef',
  buttonDisabled: '#7b847e'
};

export default {
  name: 'CourtDrawingRender',
  props: {
    drawingData: {
      type: Object,
      required: true
    },
    width: {
      type: Number,
      default: 600
    },
    height: {
      type: Number,
      default: 400
    }
  },
  data() {
    return {
      canvas: null,
      ctx: null,
      isAnimating: false,
      animationState: null, // { currentArrowIndex, startTime, arrowProgress }
      animationFrameId: null,
      config: {
        // Mehr Platz links für die drei Startkreise (Rand außerhalb des Tisches)
        canvas: { width: 640, height: 400 },
        table: {
          // Tabelle etwas schmaler und weiter rechts platzieren
          width: 500,
          height: 300,
          color: COURT_RENDER_PALETTE.table,
          borderWidth: 2,
          borderColor: COURT_RENDER_PALETTE.frameBorder,
          outerFrameWidth: 5,
          outerFrameColor: COURT_RENDER_PALETTE.frame,
          outerFrameBorderWidth: 0.5,
          outerFrameBorderColor: COURT_RENDER_PALETTE.frameBorder
        },
        horizontalLine: { color: COURT_RENDER_PALETTE.line, width: 2, gap: 10, edgeMargin: 10 },
        net: { color: COURT_RENDER_PALETTE.net, width: 4, overhang: 14, borderColor: COURT_RENDER_PALETTE.netBorder, borderWidth: 0.5 },
        serviceLine: { color: 'rgba(255,255,255,0.0)', width: 0 },
        startCircles: {
          radius: 10,
          // Abstand vom linken Canvas-Rand (größer = weiter links, da wir von tableX abziehen)
          x: 20,
          topYOffset: 35,
          bottomYOffset: 35,
          selectedColor: COURT_RENDER_PALETTE.startSelected,
          unselectedColor: COURT_RENDER_PALETTE.startMuted,
          selectedBorderColor: COURT_RENDER_PALETTE.frame,
          unselectedBorderColor: COURT_RENDER_PALETTE.startMutedBorder,
          selectedBorderWidth: 2,
          unselectedBorderWidth: 1
        },
        arrows: {
          primaryColor: COURT_RENDER_PALETTE.arrowPrimary,
          secondaryColor: COURT_RENDER_PALETTE.arrowSecondary,
          tertiaryColor: COURT_RENDER_PALETTE.arrowTertiary,
          quaternaryColor: COURT_RENDER_PALETTE.arrowQuaternary,
          width: 6,
          headLength: 24,
          vhOffsetX: 5,
          vhOffsetY: 8,
          rhOffsetX: 10,
          rhOffsetY: 0
        },
        targetCircles: {
          radius: 13,
          rightXOffset: 20,
          middleXOffset: 40,
          topYOffset: 45,
          bottomYOffset: 45,
          transparency: 0.25
        },
        leftTargetCircles: {
          radius: 10,
          leftXOffset: 20,
          rightXOffset: 40,
          topYOffset: 40,
          bottomYOffset: 40
        },
        hitMarker: {
          radius: 10.5,
          fill: COURT_RENDER_PALETTE.markerFill,
          stroke: COURT_RENDER_PALETTE.markerStroke,
          lineWidth: 1
        }
      }
    };
  },
  computed: {
    hasArrows() {
      if (!this.drawingData) return false;
      // Pfeile werden nur gezeichnet wenn ein main target existiert (tp)
      // Zusätzliche Pfeile werden nur gezeichnet wenn tp && extras.length
      // Daher muss hasArrows nur true sein, wenn ein main target existiert
      const tp = Number(this.drawingData.targetPosition);
      return !!tp;
    }
  },
  watch: {
    drawingData: {
      handler() {
        // Wenn sich drawingData ändert, stoppe laufende Animation
        if (this.isAnimating) {
          this.stopAnimation();
        }
        this.redraw();
      },
      deep: true,
      immediate: true
    }
  },
  mounted() {
    // apply custom dimensions if provided
    this.config.canvas.width = this.width || 600;
    this.config.canvas.height = this.height || 400;
    this.$nextTick(() => {
      this.init();
      this.redraw();
    });
  },
  beforeUnmount() {
    // Cleanup: stoppe Animation falls noch läuft
    this.stopAnimation();
  },
  methods: {
    init() {
      this.canvas = this.$refs.canvas;
      if (this.canvas) {
        this.ctx = this.canvas.getContext('2d');
      }
    },
    redraw() {
      if (!this.ctx) return;
      const { width, height } = this.config.canvas;
      // clear and background
      this.ctx.clearRect(0, 0, width, height);
      this.ctx.fillStyle = COURT_RENDER_PALETTE.surface;
      this.ctx.fillRect(0, 0, width, height);
      this.drawTable();
      this.drawStartCircles();
      this.drawArrowsAndLabels();
    },
    drawTable() {
      const ctx = this.ctx;
      const { table, horizontalLine, net, outerFrameWidth } = {
        ...this.config,
        outerFrameWidth: this.config.table.outerFrameWidth
      };
      const tableWidth = this.config.table.width;
      const tableHeight = this.config.table.height;
      const tableX = (this.config.canvas.width - tableWidth) / 2;
      const tableY = (this.config.canvas.height - tableHeight) / 2;

      // table fill
      ctx.fillStyle = table.color;
      ctx.fillRect(tableX, tableY, tableWidth, tableHeight);

      // table stroke
      ctx.strokeStyle = table.borderColor;
      ctx.lineWidth = table.borderWidth;
      ctx.strokeRect(tableX, tableY, tableWidth, tableHeight);

      // outer white frame
      ctx.strokeStyle = table.outerFrameColor;
      ctx.lineWidth = table.outerFrameWidth;
      ctx.strokeRect(
        tableX - table.outerFrameWidth,
        tableY - table.outerFrameWidth,
        tableWidth + table.outerFrameWidth * 2,
        tableHeight + table.outerFrameWidth * 2
      );

      // black thin frame around white
      ctx.strokeStyle = table.outerFrameBorderColor;
      ctx.lineWidth = table.outerFrameBorderWidth;
      ctx.strokeRect(
        tableX - table.outerFrameWidth - table.outerFrameBorderWidth,
        tableY - table.outerFrameWidth - table.outerFrameBorderWidth,
        tableWidth + (table.outerFrameWidth + table.outerFrameBorderWidth) * 2,
        tableHeight + (table.outerFrameWidth + table.outerFrameBorderWidth) * 2
      );

      // horizontal split line (two segments)
      ctx.strokeStyle = horizontalLine.color;
      ctx.lineWidth = horizontalLine.width;
      const centerY = tableY + tableHeight / 2;
      const centerX = tableX + tableWidth / 2;
      const gap = horizontalLine.gap;
      const edge = horizontalLine.edgeMargin;
      ctx.beginPath();
      ctx.moveTo(tableX + edge, centerY);
      ctx.lineTo(centerX - gap, centerY);
      ctx.stroke();
      ctx.beginPath();
      ctx.moveTo(centerX + gap, centerY);
      ctx.lineTo(tableX + tableWidth - edge, centerY);
      ctx.stroke();

      // net vertical
      ctx.strokeStyle = net.color;
      ctx.lineWidth = net.width;
      ctx.beginPath();
      ctx.moveTo(centerX, tableY - net.overhang);
      ctx.lineTo(centerX, tableY + tableHeight + net.overhang);
      ctx.stroke();

      ctx.strokeStyle = net.borderColor;
      ctx.lineWidth = net.borderWidth;
      ctx.beginPath();
      ctx.moveTo(centerX, tableY - net.overhang);
      ctx.lineTo(centerX, tableY + tableHeight + net.overhang);
      ctx.stroke();
    },
    drawStartCircles() {
      const ctx = this.ctx;
      const cfg = this.config.startCircles;
      const tableWidth = this.config.table.width;
      const tableHeight = this.config.table.height;
      const tableX = (this.config.canvas.width - tableWidth) / 2;
      const tableY = (this.config.canvas.height - tableHeight) / 2;

      // Startkreis links VOR dem Tisch positionieren – nur den Kreis zeichnen,
      // von dem auch der rote Pfeil startet
      const circleX = tableX - cfg.x; // Links vom Tisch
      const topY = tableY + cfg.topYOffset;
      const midY = tableY + tableHeight / 2;
      const botY = tableY + tableHeight - cfg.bottomYOffset;

      // Mapping und Fallback: bei "AS" auf 'middle'
      const selectedPos = this.resolveStartPos();
      const y = selectedPos === 'top' ? topY : selectedPos === 'bottom' ? botY : midY;

      ctx.fillStyle = cfg.selectedColor;
      ctx.beginPath();
      ctx.arc(circleX, y, cfg.radius, 0, Math.PI * 2);
      ctx.fill();
      ctx.strokeStyle = cfg.selectedBorderColor;
      ctx.lineWidth = cfg.selectedBorderWidth;
      ctx.stroke();
    },
    computeRightTargetPosition(number) {
      // Geometrie wie im Tool: nutzt rightXOffset/middleXOffset
      const tableWidth = this.config.table.width;
      const tableHeight = this.config.table.height;
      const tableX = (this.config.canvas.width - tableWidth) / 2;
      const tableY = (this.config.canvas.height - tableHeight) / 2;
      const cfg = this.config.targetCircles;

      const x1 = tableX + tableWidth - cfg.rightXOffset; // (1,2,3)
      const x3 = tableX + tableWidth / 2 + cfg.middleXOffset; // (7,8,9)
      const xdiff = x3 - x1;
      const x2 = x3 - xdiff / 2; // (4,5,6)

      const positions = {
        1: { x: x1, y: tableY + cfg.topYOffset },
        2: { x: x1, y: tableY + tableHeight / 2 },
        3: { x: x1, y: tableY + tableHeight - cfg.bottomYOffset },
        4: { x: x2, y: tableY + cfg.topYOffset },
        5: { x: x2, y: tableY + tableHeight / 2 },
        6: { x: x2, y: tableY + tableHeight - cfg.bottomYOffset },
        7: { x: x3, y: tableY + cfg.topYOffset },
        8: { x: x3, y: tableY + tableHeight / 2 },
        9: { x: x3, y: tableY + tableHeight - cfg.bottomYOffset }
      };
      return positions[number] || null;
    },
    getStartPoint() {
      // Startpunkt wie im Tool abhängig von Schlagseite (VH/RH)
      const sc = this.config.startCircles;
      const ar = this.config.arrows;
      const tblW = this.config.table.width;
      const tblH = this.config.table.height;
      const tableX = (this.config.canvas.width - tblW) / 2;
      const tableY = (this.config.canvas.height - tblH) / 2;
      const circleX = tableX - sc.x; // Kreis links vor dem Tisch
      const pos = this.resolveStartPos();
      const y = pos === 'top' ? tableY + sc.topYOffset : pos === 'bottom' ? tableY + tblH - sc.bottomYOffset : tableY + tblH / 2;
      const isVH = (this.drawingData?.strokeType || 'VH') === 'VH';
      const startX = isVH
        ? circleX + sc.radius + ar.vhOffsetX
        : circleX + sc.radius + ar.rhOffsetX;
      // VH: unterhalb seitlich (circleRadius + vhOffsetY), RH: rechts (rhOffsetY = 0)
      const startYOffset = isVH ? (sc.radius + ar.vhOffsetY) : ar.rhOffsetY;
      return { x: startX, y: y + startYOffset };
    },
    drawArrow(ctx, from, to, color, label, progress = 1.0) {
      // progress: 0.0 = nicht sichtbar, 1.0 = vollständig gezeichnet
      if (progress <= 0) return;
      
      const { width, headLength } = this.config.arrows;
      ctx.strokeStyle = color;
      ctx.fillStyle = color;
      ctx.lineWidth = width;
      
      // Berechne aktuellen Endpunkt basierend auf progress
      const currentX = from.x + (to.x - from.x) * progress;
      const currentY = from.y + (to.y - from.y) * progress;
      
      // line
      ctx.beginPath();
      ctx.moveTo(from.x, from.y);
      ctx.lineTo(currentX, currentY);
      ctx.stroke();
      
      // arrow head nur zeichnen wenn progress > 0.1 (kleine Puffer für bessere Sichtbarkeit)
      if (progress > 0.1) {
        const angle = Math.atan2(currentY - from.y, currentX - from.x);
        ctx.beginPath();
        ctx.moveTo(currentX, currentY);
        ctx.lineTo(currentX - headLength * Math.cos(angle - Math.PI / 6), currentY - headLength * Math.sin(angle - Math.PI / 6));
        ctx.lineTo(currentX - headLength * Math.cos(angle + Math.PI / 6), currentY - headLength * Math.sin(angle + Math.PI / 6));
        ctx.closePath();
        ctx.fill();
      }
    },
    drawLabelBelow(ctx, text, anchor) {
      if (!text) return;
      ctx.font = 'bold 13px Helvetica';
      const padding = 6;
      const yOffset = 23; // 5px tiefer
      const metrics = ctx.measureText(text);
      const textWidth = metrics.width;
      let x = anchor.x - textWidth / 2; // zentriert unter dem Punkt
      let y = anchor.y + yOffset;
      // clamp innerhalb Canvas
      x = Math.max(4, Math.min(this.config.canvas.width - textWidth - 4, x));
      y = Math.max(14, Math.min(this.config.canvas.height - 4, y));
      ctx.fillStyle = COURT_RENDER_PALETTE.markerFill;
      ctx.strokeStyle = COURT_RENDER_PALETTE.markerStroke;
      ctx.lineWidth = 2;
      ctx.strokeText(text, x, y);
      ctx.fillText(text, x, y);
    },
    drawArrowsAndLabels() {
      if (!this.drawingData) return;
      const ctx = this.ctx;
      const from = this.getStartPoint();

      // Sammle alle Pfeile für Animation
      const allArrows = [];
      const tp = Number(this.drawingData.targetPosition);
      
      // First arrow: to right target
      if (tp) {
        const to = this.computeRightTargetPosition(tp);
        const toEnd = { x: to.x - this.config.targetCircles.radius, y: to.y };
        allArrows.push({
          from: from,
          to: toEnd,
          toCenter: to,
          color: this.config.arrows.primaryColor,
          index: 0,
          label: `${this.drawingData.strokeType || ''} ${this.abbrevSpin(this.drawingData.spinType)}`.trim(),
          labelAnchor: this.getStartCircleCenter()
        });
      }
      
      // Additional arrows
      const extras = Array.isArray(this.drawingData.additionalStrokes) ? this.drawingData.additionalStrokes : [];
      if (tp && extras.length) {
        const colors = [
          this.config.arrows.secondaryColor,
          this.config.arrows.tertiaryColor,
          this.config.arrows.quaternaryColor
        ];
        const max = extras.length;
        const sourceRightCenter = this.computeRightTargetPosition(tp);
        let prevPoint = { x: sourceRightCenter.x - this.config.targetCircles.radius, y: sourceRightCenter.y };
        for (let i = 0; i < max; i++) {
          const stroke = extras[i];
          const side = i % 2 === 0 ? 'left' : 'right';
          let toCenter, toPoint;
          if (side === 'left') {
            const leftNum = Number(stroke.targetPosition);
            toCenter = this.computeLeftTargetPosition(leftNum);
            toPoint = { x: toCenter.x + this.config.leftTargetCircles.radius, y: toCenter.y };
          } else {
            const rightNum = Number(stroke.targetPosition);
            toCenter = this.computeRightTargetPosition(rightNum);
            toPoint = { x: toCenter.x - this.config.targetCircles.radius, y: toCenter.y };
          }
          allArrows.push({
            from: prevPoint,
            to: toPoint,
            toCenter: toCenter,
            color: colors[i % colors.length], // Zyklisch durch die verfügbaren Farben wechseln
            index: i + 1
          });
          prevPoint = toPoint;
        }
      }
      
      // Zeichne Pfeile basierend auf Animationsstatus
      allArrows.forEach((arrow, idx) => {
        let progress = 1.0;
        if (this.isAnimating && this.animationState) {
          const state = this.animationState;
          if (idx < state.currentArrowIndex) {
            // Pfeil bereits vollständig gezeichnet
            progress = 1.0;
          } else if (idx === state.currentArrowIndex) {
            // Aktuell animierter Pfeil
            progress = state.arrowProgress;
          } else {
            // Pfeil noch nicht dran
            progress = 0.0;
          }
        }
        
        // Zeichne Pfeil
        this.drawArrow(ctx, arrow.from, arrow.to, arrow.color, null, progress);
        
        // Zeichne Zielmarkierung nur wenn Pfeil vollständig animiert wurde
        if (progress >= 1.0 && arrow.toCenter) {
          this.drawHitMarker(ctx, arrow.toCenter);
        }
        
        // Zeichne Label nur wenn Pfeil vollständig
        if (progress >= 1.0 && arrow.label && arrow.labelAnchor) {
          this.drawLabelBelow(ctx, arrow.label, arrow.labelAnchor);
        }
      });
    },
    applyRenderCode(code) {
      try {
        const startMatch = code.match(/ASv([LMR])/);
        if (startMatch) {
          const map = { L: 'AS1', M: 'AS2', R: 'AS3' };
          this.drawingData.selectedStartPosition = map[startMatch[1]] || 'AS2';
          this.drawingData.selectedCirclePosition = this.drawingData.selectedStartPosition === 'AS1' ? 'top' : this.drawingData.selectedStartPosition === 'AS3' ? 'bottom' : 'middle';
        }
        // Hauptziel extrahieren (nach dem ersten → )
        const arrowParts = code.split('→').map(s => s.trim());
        if (arrowParts.length >= 2) {
          const mainLabel = arrowParts[1].split('/')[0].trim();
          const mainNum = this.labelToNumber(mainLabel);
          if (mainNum) {
            this.drawingData.targetPosition = String(mainNum);
          }
        }
        // Zusatzschläge: Segmente nach '/'
        const extras = [];
        if (code.includes('/')) {
          const extraSegments = code.split('/').slice(1);
          extraSegments.forEach(seg => {
            const m = seg.split('→')[1];
            if (m) {
              const lbl = m.trim();
              const num = this.labelToNumber(lbl);
              if (num) {
                extras.push({ targetPosition: String(num) });
              }
            }
          });
        }
        this.drawingData.additionalStrokes = extras;
      } catch (e) {
        // still draw with whatever is present
      }
    },
    labelToNumber(label) {
      const map = {
        'VH L': 1, 'M L': 2, 'RH L': 3,
        'VH H': 4, 'M H': 5, 'RH H': 6,
        'VH K': 7, 'M K': 8, 'RH K': 9
      };
      return map[label] || null;
    },
    buildCodeString() {
      if (!this.drawingData) return '';
      // Wenn ein expliziter renderCode mitgeliefert wird, verwende den
      if (this.drawingData && (this.drawingData.code || this.drawingData.renderCode)) {
        return this.drawingData.code || this.drawingData.renderCode;
      }
      // sonst: Nutze die gleiche Logik wie beim Zeichnen (resolveStartPos)
      const pos = this.resolveStartPos(); // 'top' | 'middle' | 'bottom'
      const start = pos === 'top' ? 'vL' : pos === 'bottom' ? 'vR' : 'vM';
      const strokeSide = this.drawingData.strokeType || '';
      const spin = this.abbrevSpin(this.drawingData.spinType);
      const mainTargetMap = {
        '1': 'VH L', '2': 'M L', '3': 'RH L',
        '4': 'VH H', '5': 'M H', '6': 'RH H',
        '7': 'VH K', '8': 'M K', '9': 'RH K'
      };
      let code = `AS${start} ${strokeSide} ${spin}`.trim();
      if (this.drawingData.targetPosition) {
        const main = mainTargetMap[String(this.drawingData.targetPosition)] || this.drawingData.targetPosition;
        code += ` → ${main}`;
      }
      const extras = Array.isArray(this.drawingData.additionalStrokes) ? this.drawingData.additionalStrokes : [];
      if (extras.length) {
        extras.forEach(stroke => {
          const tgt = mainTargetMap[String(stroke.targetPosition)] || stroke.targetPosition;
          code += ` / ${stroke.side} ${stroke.type} → ${tgt}`;
        });
      }
      return code;
    },
    getStartCircleCenter() {
      const cfg = this.config.startCircles;
      const tableWidth = this.config.table.width;
      const tableHeight = this.config.table.height;
      const tableX = (this.config.canvas.width - tableWidth) / 2;
      const tableY = (this.config.canvas.height - tableHeight) / 2;
      const circleX = tableX - cfg.x;
      const selectedPos = this.resolveStartPos();
      const topY = tableY + cfg.topYOffset;
      const midY = tableY + tableHeight / 2;
      const botY = tableY + tableHeight - cfg.bottomYOffset;
      const y = selectedPos === 'top' ? topY : selectedPos === 'bottom' ? botY : midY;
      return { x: circleX, y };
    },
    resolveStartPos() {
      // 1) bevorzugt AS1/AS2/AS3 aus drawingData.selectedStartPosition
      const key = this.drawingData?.selectedStartPosition;
      if (key === 'AS1') return 'top';
      if (key === 'AS2') return 'middle';
      if (key === 'AS3') return 'bottom';
      // 2) Fallback über selectedCirclePosition (top/middle/bottom)
      const circlePos = this.drawingData?.selectedCirclePosition;
      if (circlePos === 'top' || circlePos === 'middle' || circlePos === 'bottom') return circlePos;
      // 3) Default Mitte
      return 'middle';
    },
    drawHitMarker(ctx, pos) {
      if (!pos) return;
      const mk = this.config.hitMarker;
      ctx.beginPath();
      ctx.arc(pos.x, pos.y, mk.radius, 0, Math.PI * 2);
      ctx.fillStyle = mk.fill;
      ctx.fill();
      ctx.lineWidth = mk.lineWidth;
      ctx.strokeStyle = mk.stroke;
      ctx.stroke();
    },
    computeLeftTargetPosition(number) {
      // Spiegelung wie im Tool: nutzt leftTargetCircles Offsets
      const tableWidth = this.config.table.width;
      const tableHeight = this.config.table.height;
      const tableX = (this.config.canvas.width - tableWidth) / 2;
      const tableY = (this.config.canvas.height - tableHeight) / 2;
      const cfg = this.config.leftTargetCircles;

      const x1 = tableX + cfg.leftXOffset; // linke Spalte (Lang)
      const x3 = tableX + tableWidth / 2 - cfg.rightXOffset; // nah am Netz (Kurz)
      const xdiff = x3 - x1;
      const x2 = x3 - xdiff / 2;

      // Gespiegelte Y-Zuordnung wie im Tool:
      // 1,4,7 = unten (VH gespiegelt)
      // 2,5,8 = mitte
      // 3,6,9 = oben (RH gespiegelt)
      const positions = {
        1: { x: x1, y: tableY + tableHeight - cfg.bottomYOffset },
        2: { x: x1, y: tableY + tableHeight / 2 },
        3: { x: x1, y: tableY + cfg.topYOffset },
        4: { x: x2, y: tableY + tableHeight - cfg.bottomYOffset },
        5: { x: x2, y: tableY + tableHeight / 2 },
        6: { x: x2, y: tableY + cfg.topYOffset },
        7: { x: x3, y: tableY + tableHeight - cfg.bottomYOffset },
        8: { x: x3, y: tableY + tableHeight / 2 },
        9: { x: x3, y: tableY + cfg.topYOffset }
      };
      return positions[number] || null;
    },
    abbrevSpin(spin) {
      if (!spin) return '';
      const map = {
        Unterschnitt: 'US',
        Überschnitt: 'OS',
        Seitschnitt: 'SR',
        Seitunterschnitt: 'SU',
        Gegenläufer: 'GL'
      };
      return map[spin] || spin;
    },
    startAnimation() {
      if (this.isAnimating || !this.hasArrows) return;
      
      // Zähle Anzahl der Pfeile - muss exakt der Logik in drawArrowsAndLabels() entsprechen
      const tp = Number(this.drawingData.targetPosition);
      const extras = Array.isArray(this.drawingData.additionalStrokes) ? this.drawingData.additionalStrokes : [];
      // Erster Pfeil wird nur hinzugefügt wenn tp truthy
      // Zusätzliche Pfeile werden nur hinzugefügt wenn tp truthy UND extras.length > 0
      const mainArrow = tp ? 1 : 0;
      const additionalArrows = (tp && extras.length) ? extras.length : 0;
      const totalArrows = mainArrow + additionalArrows;
      
      if (totalArrows === 0) return;
      
      this.isAnimating = true;
      this.animationState = {
        currentArrowIndex: 0,
        startTime: performance.now(),
        arrowProgress: 0.0,
        totalArrows: totalArrows
      };
      
      this.animateFrame();
    },
    animateFrame() {
      if (!this.isAnimating || !this.animationState) {
        this.stopAnimation();
        return;
      }
      
      const now = performance.now();
      const state = this.animationState;
      const elapsed = now - state.startTime;
      const durationPerArrow = 1000; // 1 Sekunde pro Pfeil
      
      // Berechne aktuellen Pfeil-Index basierend auf vergangener Zeit
      const currentArrowIndex = Math.floor(elapsed / durationPerArrow);
      
      if (currentArrowIndex >= state.totalArrows) {
        // Animation abgeschlossen - alle Pfeile wurden animiert
        this.stopAnimation();
        return;
      }
      
      // Berechne Progress für den aktuellen Pfeil (0.0 bis 1.0 innerhalb seiner Sekunde)
      const timeWithinCurrentArrow = elapsed % durationPerArrow;
      const arrowProgress = Math.min(1.0, timeWithinCurrentArrow / durationPerArrow);
      
      state.currentArrowIndex = currentArrowIndex;
      state.arrowProgress = arrowProgress;
      
      // Neuzeichnen
      this.redraw();
      
      // Nächster Frame
      this.animationFrameId = requestAnimationFrame(() => this.animateFrame());
    },
    stopAnimation() {
      this.isAnimating = false;
      this.animationState = null;
      if (this.animationFrameId !== null) {
        cancelAnimationFrame(this.animationFrameId);
        this.animationFrameId = null;
      }
      // Finales Redraw um alle Pfeile vollständig zu zeigen
      this.redraw();
    }
  }
};
</script>

<style scoped>
.render-container {
  width: 100%;
}

canvas { 
  display: block; 
  max-width: 100%; 
  height: auto; 
}

.render-canvas {
  margin: 0 auto;
}

.animation-controls {
  text-align: center;
  margin-bottom: 1rem;
}

.btn-animate {
  padding: 0.5rem 1rem;
  font-size: 0.9rem;
  font-weight: 600;
  border: 1px solid transparent;
  border-radius: 10px;
  background: linear-gradient(135deg, var(--primary-color), var(--primary-hover));
  color: var(--text-on-primary);
  cursor: pointer;
  transition: opacity 0.2s ease, transform 0.2s ease;
}

.btn-animate:hover:not(:disabled) {
  opacity: 0.95;
  transform: translateY(-1px);
}

.btn-animate:disabled {
  opacity: 0.6;
  cursor: not-allowed;
  background-color: #7b847e;
  border-color: #7b847e;
}
</style>
