/**
 * 마커 레이어 (deck.gl ScatterplotLayer)
 * - 40만척+ 실시간 렌더링 (GPU 가속)
 * - transitions: 위치 변경 시 부드러운 보간 애니메이션
 * - DataFilterExtension: 뷰포트 외 데이터 렌더 스킵
 */
import { ScatterplotLayer } from 'deck.gl';
import { DataFilterExtension } from '@deck.gl/extensions';

export interface MarkerData {
  lat: number;
  lng: number;
  color?: string;
  radius?: number;
  label?: string;
  /** DataFilterExtension 필터 값 (1=표시, 0=숨김) */
  filterValue?: number;
}

function hexToRgb(hex: string): [number, number, number] {
  const r = parseInt(hex.slice(1, 3), 16);
  const g = parseInt(hex.slice(3, 5), 16);
  const b = parseInt(hex.slice(5, 7), 16);
  return [r, g, b];
}

/** ScatterplotLayer 생성 — transitions + DataFilterExtension 기본 적용 */
export function createMarkerLayer(
  id: string,
  data: MarkerData[],
  defaultColor = '#3b82f6',
  defaultRadius = 800,
) {
  return new ScatterplotLayer({
    id,
    data,
    pickable: true,
    getPosition: (d: MarkerData) => [d.lng, d.lat],
    getRadius: (d: MarkerData) => d.radius ?? defaultRadius,
    getFillColor: (d: MarkerData) => [...hexToRgb(d.color ?? defaultColor), 220],
    getLineColor: (d: MarkerData) => [...hexToRgb(d.color ?? defaultColor), 255],
    lineWidthMinPixels: 1,
    radiusUnits: 'meters',
    radiusMinPixels: 3,
    radiusMaxPixels: 20,
    // 위치 변경 시 부드러운 보간 (실시간 AIS 위치 업데이트)
    transitions: {
      getPosition: { duration: 1000, enter: () => [0, 0, 0] },
      getRadius: { duration: 300 },
    },
    // DataFilter: filterValue=0인 마커는 GPU에서 렌더 스킵
    extensions: [new DataFilterExtension({ filterSize: 1 })],
    getFilterValue: (d: MarkerData) => d.filterValue ?? 1,
    filterRange: [0.5, 1.5],
    // deck.gl diff 최적화: data 참조가 같으면 GPU 재전송 없음
    updateTriggers: {
      getPosition: data,
      getFillColor: data,
    },
  });
}

/** 반경 원 표시용 ScatterplotLayer */
export function createRadiusLayer(
  id: string,
  data: { lat: number; lng: number; radius: number; color: string }[],
  opacity = 0.15,
) {
  return new ScatterplotLayer({
    id,
    data,
    pickable: false,
    getPosition: (d) => [d.lng, d.lat],
    getRadius: (d) => d.radius,
    getFillColor: (d) => [...hexToRgb(d.color), Math.round(opacity * 255)],
    getLineColor: (d) => [...hexToRgb(d.color), Math.round(opacity * 3 * 255)],
    lineWidthMinPixels: 1,
    stroked: true,
    filled: true,
    radiusUnits: 'meters',
    transitions: {
      getRadius: { duration: 500 },
    },
  });
}
