import {
  BindingUtil,
  TLBaseBinding,
  BindingOnShapeChangeOptions,
  BindingOnShapeDeleteOptions,
  T,
  sortByIndex,
} from 'tldraw'
import { PolylinieShape, PolyliniePoint, PolylinieConnectionProps } from '../shapes/shape-types'

export type PolylinieConnectionBinding = TLBaseBinding<
  'polylinie-connection',
  PolylinieConnectionProps
>

export class PolylinieBindingUtil extends BindingUtil<PolylinieConnectionBinding> {
  static override type = 'polylinie-connection' as const

  static override props = {
    terminal: T.string,
    normalizedAnchor: T.object({
      x: T.number,
      y: T.number,
    }),
  }

  override getDefaultProps(): PolylinieConnectionProps {
    return {
      terminal: 'end',
      normalizedAnchor: { x: 0, y: 0 },
    }
  }

  override onAfterChangeToShape(options: BindingOnShapeChangeOptions<PolylinieConnectionBinding>) {
    const { binding, shapeAfter } = options

    const polyShape = this.editor.getShape<PolylinieShape>(binding.fromId)
    if (!polyShape) return

    const targetX = shapeAfter.x
    const targetY = shapeAfter.y

    const anchor = binding.props.normalizedAnchor
    const termPt = this._getTerminalPoint(polyShape, binding.props.terminal)
    const dx = targetX + anchor.x - (polyShape.x + termPt.x)
    const dy = targetY + anchor.y - (polyShape.y + termPt.y)

    if (Math.abs(dx) < 0.01 && Math.abs(dy) < 0.01) return

    const points = { ...polyShape.props.points }
    const sorted = Object.values(points).sort(sortByIndex)

    if (sorted.length < 2) return

    const isEnd = binding.props.terminal === 'end'
    const terminalIdx = isEnd ? sorted.length - 1 : 0
    const terminal = sorted[terminalIdx]

    points[terminal.id] = {
      ...terminal,
      x: terminal.x + dx,
      y: terminal.y + dy,
    }

    if (sorted.length >= 3) {
      const adjIdx = isEnd ? sorted.length - 2 : 1
      const adj = sorted[adjIdx]
      points[adj.id] = {
        ...adj,
        x: adj.x + dx * 0.5,
        y: adj.y + dy * 0.5,
      }
    }

    this.editor.updateShape<PolylinieShape>({
      id: polyShape.id,
      type: 'polylinie',
      props: { points },
    })
  }

  override onBeforeDeleteToShape(_options: BindingOnShapeDeleteOptions<PolylinieConnectionBinding>) {
    // Binding entfernen, Polylinie behalten
  }

  private _getTerminalPoint(
    shape: PolylinieShape,
    terminal: string
  ): { x: number; y: number } {
    const sorted = Object.values(shape.props.points).sort(sortByIndex)
    if (sorted.length === 0) return { x: 0, y: 0 }
    if (terminal === 'start') return sorted[0]
    return sorted[sorted.length - 1]
  }
}
