import {
  MeasureDistanceMode,
  type FeatureCollection,
  type ModeProps,
} from '@deck.gl-community/editable-layers'
import type { BasePointerEvent } from 'node_modules/@deck.gl-community/editable-layers/dist/edit-modes/types'
import { EditType } from '../../../editable/const'
import type { ValueOf } from 'type-fest'
import type { MapMeasurementUnitAuto } from '../const'
import type { MeasurementToolsTextProps } from '../types'
import { getTextLayerFormattedDistance } from '../utils'

/**
 * Custom distance measurement mode that extends `MeasureDistanceMode` with keyboard controls and formatted tooltip support.
 *
 * @remarks
 * Supports Enter to finish and Escape to cancel a measurement session.
 * Emits edit events with distance, positions, and finished state on each click.
 */
export class CustomMeasureDistanceMode extends MeasureDistanceMode {
  override handleClick(
    event: BasePointerEvent,
    props: ModeProps<FeatureCollection>,
  ): void {
    super.handleClick(event, props)

    props.onEdit({
      // data is the same
      updatedData: props.data,
      editType: EditType.addPosition,
      editContext: {
        distance: this._currentDistance,
        finished: this._isMeasuringSessionFinished,
        positions: this.getClickSequence(),
      },
    })
  }

  override handleKeyUp(
    event: KeyboardEvent,
    props: ModeProps<FeatureCollection>,
  ) {
    if (this._isMeasuringSessionFinished) return

    event.stopPropagation()
    const { key } = event

    const clickSequenceLength = this.getClickSequence().length

    let editType: ValueOf<typeof EditType> = EditType.finish

    switch (key) {
      case 'Escape':
        props.onEdit({
          updatedData: {
            type: 'FeatureCollection',
            features: [],
          },
          editType: EditType.cancel,
          editContext: {},
        })
        break
      case 'Enter':
        this._isMeasuringSessionFinished = true
        if (clickSequenceLength === 1) {
          this.resetClickSequence()
          editType = EditType.cancel
        }
        // force update drawings
        props.onUpdateCursor('cell')
        props.onEdit({
          updatedData: props.data,
          editType,
          editContext: {
            finished: this._isMeasuringSessionFinished,
          },
        })
        break
      default:
        break
    }
  }

  override resetClickSequence() {
    super.resetClickSequence()
    this._isMeasuringSessionFinished = false
    this._currentTooltips = []
    this._currentDistance = 0
  }

  getTooltipText({
    meters,
    locale,
    unit,
    options,
  }: {
    meters: number
    unit: ValueOf<typeof MapMeasurementUnitAuto>
    locale: string
    options?: MeasurementToolsTextProps
  }): string {
    return getTextLayerFormattedDistance({
      meters,
      locale,
      unit,
      options,
    })
  }
}
