import { EditableGeoJsonLayer } from '@deck.gl-community/editable-layers'
import type { UpdateParameters } from '@deck.gl/core'
import { EventManager } from 'mjolnir.js'
import { EVENT_TYPES } from '../use-event-manager'

/**
 * Custom extension of `EditableGeoJsonLayer` that integrates with a shared event manager for coordinated map interactions.
 *
 * @remarks
 * Overrides event handler registration to use a custom `EventManager` instance when provided,
 * ensuring lasso and measurement tool interactions are properly prioritized.
 */
export class CustomEditableGeojsonLayer extends EditableGeoJsonLayer {
  declare props: EditableGeoJsonLayer['props'] & {
    eventManager?: EventManager | null
  }

  override updateState({
    props,
    oldProps,
    context,
    changeFlags,
  }: UpdateParameters<this>) {
    if (props.eventManager !== oldProps.eventManager) {
      this._removeEventHandlers(props.eventManager)
      this._removeEventHandlers(oldProps.eventManager)
      this._addEventHandlers()
    }
    super.updateState({ props, oldProps, context, changeFlags })
  }

  override _addEventHandlers() {
    const eventManager = this._getEventManager()!
    // _editableLayerState is not in the types, but it's a private property that can be accessed
    // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
    const { eventHandler } = this.state._editableLayerState

    for (const eventType of EVENT_TYPES) {
      // error derived from the _editableLayerState. The type is not exists
      // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
      eventManager.on(eventType, eventHandler, {
        priority: 100,
      })
    }
  }

  override _removeEventHandlers(_eventManager?: EventManager | null) {
    const eventManager = _eventManager ?? this._getEventManager()!
    // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
    const { eventHandler } = this.state._editableLayerState

    for (const eventType of EVENT_TYPES) {
      // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
      eventManager.off(eventType as 'anyclick', eventHandler)
    }
  }

  _getEventManager() {
    return (
      this.props.eventManager ??
      // @ts-expect-error accessing protected props
      this.context.deck.eventManager
    )
  }
}

CustomEditableGeojsonLayer.layerName = 'CustomEditableGeojsonLayer'
