<template>
  <div 
    class="video-frame-container" 
    tabindex="0" 
    ref="container"
    @keydown="handleKeyDown"
    @focus="handleFocus"
    @blur="handleBlur">
    <div class="video-frame" 
         ref="imageContainer"
         :style="frameStyle"
         @contextmenu.prevent
         @wheel.prevent="handleZoom"
         @mousedown="handleMouseDown"
         @mousemove="handleMouseMove"
         @mouseup="stopPan"
         @mouseleave="stopPan">
      <div class="image-container" :style="transformStyle">
        <img v-if="thumbnail" 
             :src="thumbnail" 
             alt="Video frame"
             @load="initializeImage"
             ref="image"
             class="video-image" />
        <div v-for="(point, index) in calibrationPoints" 
             :key="index"
             class="calibration-point"
             :class="{ 'selected-point': selectedFieldPoint && Number(selectedFieldPoint.index) === Number(index) }"
             :style="{
               left: `${point.x}px`,
               top: `${point.y}px`
             }">
        </div>
        <div v-for="(line, id) in calibrationLines"
             :key="'line-'+id"
             class="calibration-polyline">
          <svg class="polyline-svg">
            <g v-for="(line, id) in calibrationLines" :key="id">
              <polyline
                :points="formatPoints(line.points)"
                :class="{ 'selected-line': selectedFieldLine && selectedFieldLine.id === id }"
                fill="none"
                stroke="#00FF15"
                stroke-width="2"
              />
              <circle v-for="(point, index) in line.points"
                      :key="'point-'+index"
                      :cx="point.x"
                      :cy="point.y"
                      r="2"
                      class="polyline-point"
                      :class="{
                        'selected-line-point': selectedFieldLine && selectedFieldLine.id === id,
                        'dragging': isDraggingPoint && draggedLineId === id && selectedPointIndex === index,
                        'shared-point': sharedPoints.has(`${id}-${index}`),
                        'hoverable': isCtrlPressed && selectedFieldLine
                      }"
              />
            </g>
          </svg>
        </div>
        <div v-for="(point, index) in currentLinePoints"
             :key="'temp-'+index"
             class="calibration-point temp-point"
             :style="{
               left: `${point.x}px`,
               top: `${point.y}px`
             }" />
        <svg class="temp-polyline-svg" v-if="currentLinePoints.length > 0">
          <polyline
            :points="getPolylinePoints(currentLinePoints)"
            stroke="#FFC107"
            stroke-dasharray="5,5"
            fill="none"
            stroke-width="2"
          />
        </svg>
      </div>
    </div>
    <div class="save-section">
      <KeyboardShortcuts />
      <button 
        class="action-btn clear-btn"
        :disabled="Object.keys(calibrationLines).length === 0 && Object.keys(calibrationPoints).length === 0"
        @click="clearCalibration"
      >
        Clear
      </button>
      <button 
        class="action-btn process-btn"
        :disabled="Object.keys(calibrationLines).length === 0 && Object.keys(calibrationPoints).length === 0"
        @click="processCalibration"
      >
        Traiter la calibration
      </button>
    </div>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted } from 'vue'
import KeyboardShortcuts from './KeyboardShortcuts.vue'

// Props
const props = defineProps({
  thumbnail: {
    type: String,
    default: null
  },
  calibrationPoints: {
    type: Object,
    default: () => ({})
  },
  calibrationLines: {
    type: Object,
    default: () => ({})
  },
  selectedFieldPoint: {
    type: Object,
    default: null
  },
  selectedFieldLine: {
    type: Object,
    default: null
  }
})

// Emits
const emit = defineEmits([
  'update:calibrationPoints',
  'update:calibrationLines',
  'update:selectedFieldPoint',
  'update:selectedFieldLine',
  'clear-calibration',
  'process-calibration'
])

// Refs
const container = ref(null)
const imageContainer = ref(null)
const image = ref(null)

// Data
const scale = ref(1)
const translation = ref({ x: 0, y: 0 })
const aspectRatio = ref(1)
const imageSize = ref({ width: 0, height: 0 })
const isPanning = ref(false)
const isMiddleMouseDown = ref(false)
const lastMousePosition = ref({ x: 0, y: 0 })
const currentLinePoints = ref([])
const isDrawingLine = ref(false)
const isDraggingPoint = ref(false)
const selectedPointIndex = ref(null)
const draggedLineId = ref(null)
const proximityThreshold = ref(10)
const tempPoint = ref(null)
const isCtrlPressed = ref(false)
const sharedPoints = ref(new Set())
const draggedPoints = ref([])
const isCreatingLine = ref(false)

// Computed
const frameStyle = computed(() => {
  if (!aspectRatio.value) return {}
  
  const container = imageContainer.value?.parentElement
  if (!container) return {}
  
  const parentWidth = container.clientWidth
  const parentHeight = container.clientHeight
  
  let width, height
  
  if (parentWidth / parentHeight > aspectRatio.value) {
    height = parentHeight
    width = height * aspectRatio.value
  } else {
    width = parentWidth
    height = width / aspectRatio.value
  }
  
  return {
    width: `${width}px`,
    height: `${height}px`
  }
})

const transformStyle = computed(() => {
  return {
    transform: `translate(${translation.value.x}px, ${translation.value.y}px) scale(${scale.value})`,
    transformOrigin: '0 0'
  }
})

// Methods
const initializeImage = (event) => {
  const img = event.target
  
  imageSize.value = {
    width: img.naturalWidth,
    height: img.naturalHeight
  }
  
  aspectRatio.value = imageSize.value.width / imageSize.value.height
}

const handleZoom = (event) => {
  const zoomFactor = 0.1
  const delta = Math.sign(event.deltaY) * -1
  const newScale = scale.value + delta * zoomFactor
  
  const oldScale = scale.value
  scale.value = Math.min(Math.max(newScale, 1), 15)
  
  if (scale.value === 1) {
    translation.value = { x: 0, y: 0 }
    return
  }
  
  if (scale.value !== oldScale) {
    const rect = imageContainer.value.getBoundingClientRect()
    const mouseX = event.clientX - rect.left
    const mouseY = event.clientY - rect.top

    const pointX = (mouseX - translation.value.x) / oldScale
    const pointY = (mouseY - translation.value.y) / oldScale

    translation.value = {
      x: mouseX - (pointX * scale.value),
      y: mouseY - (pointY * scale.value)
    }
  }
}

const handleMouseDown = (event) => {
  if (event.button === 1) { // Clic molette
    isMiddleMouseDown.value = true
    lastMousePosition.value = {
      x: event.clientX,
      y: event.clientY
    }
    event.preventDefault()
    return
  }

  // Gestion des points
  if (event.button === 0 && props.selectedFieldPoint) {
    const rect = imageContainer.value.getBoundingClientRect()
    const x = event.clientX - rect.left
    const y = event.clientY - rect.top
    
    const newPoints = { ...props.calibrationPoints }
    newPoints[props.selectedFieldPoint.index] = {
      x: (x - translation.value.x) / scale.value,
      y: (y - translation.value.y) / scale.value
    }
    emit('update:calibrationPoints', newPoints)
    return
  }

  // Gestion des lignes
  if (event.button === 2 && props.selectedFieldLine) {
    if (currentLinePoints.value.length >= 2) {
      const newLines = { ...props.calibrationLines }
      newLines[props.selectedFieldLine.id] = {
        points: [...currentLinePoints.value]
      }
      emit('update:calibrationLines', newLines)
      currentLinePoints.value = []
      isCreatingLine.value = false
    }
    return
  }

  if (event.button === 0) {
    const rect = imageContainer.value.getBoundingClientRect()
    const mouseX = event.clientX - rect.left
    const mouseY = event.clientY - rect.top
    
    const x = (mouseX - translation.value.x) / scale.value
    const y = (mouseY - translation.value.y) / scale.value

    if (isDraggingPoint.value) {
      const newLines = { ...props.calibrationLines }
      draggedPoints.value.forEach(({ lineId, pointIndex }) => {
        if (newLines[lineId] && Array.isArray(newLines[lineId].points)) {
          newLines[lineId].points[pointIndex] = { x, y }
        }
      })
      emit('update:calibrationLines', newLines)
      
      isDraggingPoint.value = false
      draggedPoints.value = []
      tempPoint.value = null
      return
    }

    if (!isCreatingLine.value) {
      if (isCtrlPressed.value) {
        const nearestPoint = findLineByPoint(x, y)
        
        if (nearestPoint) {
          if (currentLinePoints.value.length === 0) {
            isCreatingLine.value = true
            currentLinePoints.value.push(nearestPoint.point)
            sharedPoints.value.add(`${nearestPoint.lineId}-${nearestPoint.pointIndex}`)
            return
          }
        }
      }
      
      const nearestPoint = findLineByPoint(x, y)
      if (nearestPoint) {
        isDraggingPoint.value = true
        const sharedLines = findAllLinesWithPoint(nearestPoint.point.x, nearestPoint.point.y)
        draggedPoints.value = sharedLines.map(line => ({
          lineId: line.lineId,
          pointIndex: line.pointIndex
        }))
        tempPoint.value = { ...nearestPoint.point }
        return
      } else if (props.selectedFieldLine) {
        isCreatingLine.value = true
        currentLinePoints.value = [{ x, y }]
      }
    } else {
      if (isCtrlPressed.value) {
        const nearestPoint = findLineByPoint(x, y)
        if (nearestPoint && nearestPoint.lineId !== props.selectedFieldLine.id) {
          currentLinePoints.value.push(nearestPoint.point)
          sharedPoints.value.add(`${nearestPoint.lineId}-${nearestPoint.pointIndex}`)
          return
        }
      }
      currentLinePoints.value.push({ x, y })
    }
  }
}

const handleMouseMove = (event) => {
  if (isMiddleMouseDown.value) {
    const dx = event.clientX - lastMousePosition.value.x
    const dy = event.clientY - lastMousePosition.value.y
    
    const container = imageContainer.value
    const img = image.value
    
    if (!container || !img) return
    
    const containerRect = container.getBoundingClientRect()
    const imageRect = img.getBoundingClientRect()
    
    const minX = containerRect.width - imageRect.width * scale.value
    const minY = containerRect.height - imageRect.height * scale.value
    
    const newX = Math.min(0, Math.max(minX, translation.value.x + dx))
    const newY = Math.min(0, Math.max(minY, translation.value.y + dy))
    
    translation.value.x = newX
    translation.value.y = newY
    
    lastMousePosition.value = {
      x: event.clientX,
      y: event.clientY
    }
    return
  }

  if (isDraggingPoint.value && draggedPoints.value.length > 0) {
    const rect = imageContainer.value.getBoundingClientRect()
    const mouseX = event.clientX - rect.left
    const mouseY = event.clientY - rect.top
    
    const x = (mouseX - translation.value.x) / scale.value
    const y = (mouseY - translation.value.y) / scale.value

    const newLines = { ...props.calibrationLines }
    draggedPoints.value.forEach(({ lineId, pointIndex }) => {
      if (newLines[lineId] && Array.isArray(newLines[lineId].points)) {
        newLines[lineId].points[pointIndex] = { x, y }
      }
    })
    
    emit('update:calibrationLines', newLines)
  }
}

const stopPan = () => {
  isMiddleMouseDown.value = false
}

const handleKeyDown = (event) => {
  if (event.key === 'Control') {
    isCtrlPressed.value = true
  } else if (event.key === 'Delete' || event.key === 'Backspace') {
    deleteLine()
  }
}

const handleKeyUp = (event) => {
  if (event.key === 'Control') {
    isCtrlPressed.value = false
  }
}

const handleFocus = () => {
  console.log('Container focused')
}

const handleBlur = () => {
  console.log('Container lost focus')
}

const getPolylinePoints = (points) => {
  if (!points) return ''
  return points.map(p => `${p.x},${p.y}`).join(' ')
}

const formatPoints = (points) => {
  if (!points) return ''
  return points.map(p => `${p.x},${p.y}`).join(' ')
}

const findLineByPoint = (x, y) => {
  for (const [lineId, line] of Object.entries(props.calibrationLines)) {
    const points = line.points
    for (let i = 0; i < points.length; i++) {
      const point = points[i]
      const dx = point.x - x
      const dy = point.y - y
      const distance = Math.sqrt(dx * dx + dy * dy)
      
      if (distance < proximityThreshold.value) {
        return {
          lineId,
          pointIndex: i,
          point
        }
      }
    }
  }
  return null
}

const findAllLinesWithPoint = (x, y) => {
  const sharedLines = []
  for (const [lineId, line] of Object.entries(props.calibrationLines)) {
    const points = line.points
    for (let i = 0; i < points.length; i++) {
      const point = points[i]
      const dx = point.x - x
      const dy = point.y - y
      const distance = Math.sqrt(dx * dx + dy * dy)
      
      if (distance < proximityThreshold.value) {
        sharedLines.push({
          lineId,
          pointIndex: i,
          point
        })
      }
    }
  }
  return sharedLines
}

const deleteLine = () => {
  if (props.selectedFieldLine) {
    const newLines = { ...props.calibrationLines }
    if (newLines[props.selectedFieldLine.id]) {
      const points = newLines[props.selectedFieldLine.id].points
      points.forEach((_, index) => {
        sharedPoints.value.delete(`${props.selectedFieldLine.id}-${index}`)
      })
    }
    delete newLines[props.selectedFieldLine.id]
    emit('update:calibrationLines', newLines)
    emit('update:selectedFieldLine', null)
    currentLinePoints.value = []
    isCreatingLine.value = false
  }
}

const clearCalibration = () => {
  emit('clear-calibration')
}

const processCalibration = () => {
  emit('process-calibration')
}

// Lifecycle
onMounted(() => {
  window.addEventListener('keydown', handleKeyDown)
  window.addEventListener('keyup', handleKeyUp)
})

onUnmounted(() => {
  window.removeEventListener('keydown', handleKeyDown)
  window.removeEventListener('keyup', handleKeyUp)
})

// Expose imageSize for parent component
defineExpose({
  imageSize
})
</script>

<style scoped>
.video-frame-container {
  flex: 2;
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  min-height: 0;
  border-radius: 4px;
  padding: 10px;
  outline: none;
}

.video-frame {
  position: relative;
  overflow: hidden;
  width: 100%;
  height: calc(100% - 50px);
  margin-bottom: 45px;
}

.image-container {
  position: absolute;
  top: 0;
  left: 0;
  will-change: transform;
}

.video-image {
  display: block;
  max-width: 100%;
  height: auto;
}

.calibration-point {
  position: absolute;
  width: 12px;
  height: 12px;
  background-color: rgb(0, 255, 21);
  border-radius: 50%;
  transform: translate(-50%, -50%);
  pointer-events: none;
  box-shadow: 0 0 6px rgba(76, 175, 80, 0.8),
              0 0 12px rgba(76, 175, 80, 0.5);
}

.selected-point {
  background-color: #FFC107;
  box-shadow: 0 0 8px rgba(255, 193, 7, 0.8),
              0 0 15px rgba(255, 193, 7, 0.5);
}

.save-section {
  position: absolute;
  bottom: 10px;
  left: 10px;
  display: flex;
  gap: 10px;
}

.action-btn {
  display: flex;
  align-items: center;
  padding: 0.5rem 1rem;
  background: rgba(255, 255, 255, 0.1);
  color: #ffffff;
  border: 1px solid #555;
  border-radius: 6px;
  font-weight: 600;
  font-size: 0.9rem;
  cursor: pointer;
  transition: all 0.3s ease;
}

.action-btn:hover:not(:disabled) {
  background: rgba(255, 255, 255, 0.15);
  border-color: var(--color-primary);
  color: var(--color-primary);
  transform: translateY(-2px);
  box-shadow: 0 4px 15px rgba(217, 255, 4, 0.2);
}

.action-btn:disabled {
  background: rgba(255, 255, 255, 0.05);
  color: #666;
  border-color: #333;
  cursor: not-allowed;
  transform: none;
  box-shadow: none;
}

.process-btn {
  background: var(--color-primary);
  color: var(--color-secondary);
  border-color: var(--color-primary);
}

.process-btn:hover:not(:disabled) {
  background: var(--color-primary-soft);
  border-color: var(--color-primary-soft);
  color: var(--color-secondary);
  box-shadow: 0 4px 15px rgba(217, 255, 4, 0.4);
}

.calibration-polyline {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.polyline-svg {
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
}

.polyline-svg polyline {
  transition: stroke-width 0.2s;
}

.selected-line {
  stroke-width: 2;
  stroke: #FFC107 !important;
}

.polyline-point {
  fill: #00FF15;
  stroke: white;
  stroke-width: 0.5;
  transition: all 0.2s ease;
  pointer-events: all;
  cursor: pointer;
}

.polyline-point:hover {
  fill: #FFC107;
  r: 3;
  stroke-width: 2;
}

.selected-line .polyline-point {
  cursor: grab;
}

.polyline-point.dragging {
  fill: #FF4081;
  r: 4;
  stroke-width: 3;
}

.selected-line-point {
  fill: #FFC107;
  r: 2;
  stroke-width: 1;
}

.temp-point {
  background-color: #FFC107;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  border: 2px solid white;
  z-index: 2;
}

.temp-polyline-svg {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}

.polyline-point.shared-point {
  fill: #FFC107;
  stroke: #FF4081;
  stroke-width: 2;
  r: 4;
  animation: pulse 2s infinite;
}

.polyline-point.hoverable {
  cursor: pointer;
  filter: brightness(1.2);
}

@keyframes pulse {
  0% {
    stroke-width: 2;
    stroke-opacity: 1;
  }
  50% {
    stroke-width: 3;
    stroke-opacity: 0.5;
  }
  100% {
    stroke-width: 2;
    stroke-opacity: 1;
  }
}
</style> 