import type { GeoJsonEditMode } from '@deck.gl-community/editable-layers'
import type { Color } from '@deck.gl/core'
import type { LengthUnits } from 'convert-units/definitions/length'
import type {
  MeasurementMode,
  MeasurementModes,
  MeasurementUnit,
  MeasurementUnitOption,
  MeasurementUnits,
} from '../../types'
import type { ValueOf } from 'type-fest'
import { CustomMeasureAreaMode } from './modes/custom-measurement-area.class'
import { CustomMeasureBufferMode } from './modes/custom-measurement-buffer.class'
import { CustomMeasureDistanceMode } from './modes/custom-measurement-distance.class'
import type { DefaultMeasureToolProps } from './types'
import type { AreaUnits } from 'convert-units/definitions/area'

export const MAP_MEASURE_LAYER_ID = 'mapMeasureLayer'

export const DEFAULT_LAYER_PROPS = {
  id: MAP_MEASURE_LAYER_ID,
  pickable: false,
  billboard: false,
  editHandlePointRadiusUnits: 'pixels',
  editHandlePointRadiusMinPixels: 1,
  editHandlePointRadiusMaxPixels: 12,
  lineWidthMinPixels: 2,
  editHandlePointStrokeWidth: 3,
  getEditHandlePointRadius: 3,
  _subLayerProps: {
    tooltips: {
      fontFamily: 'Open Sans, Inter, sans-serif',
      fontWeight: 600,
      getSize: 12,
      lineHeight: 1.4545,
      getPixelOffset: [0, 20],
      getTextAnchor: 'middle',
      getAlignmentBaseline: 'center',
      updateTriggers: {},
    },
    guides: {
      getLineWidth: 2,
    },
  },
} as const

export const DEFAULT_COLORS: Record<string, Color> = {
  editing: [23, 102, 214, 255],
  finished: [71, 219, 153, 255],
  point: [255, 255, 255, 255],
} as const

export const DEFAULT_PROPS: DefaultMeasureToolProps = {
  styles: {
    colors: {
      editing: DEFAULT_COLORS.editing!,
      finished: DEFAULT_COLORS.finished!,
      point: DEFAULT_COLORS.point!,
    },
  },
} as const

export const MapMeasurementUnit = {
  kilometer: 'kilometer',
  meter: 'meter',
  centimeter: 'centimeter',
  milimeter: 'milimeter',
  mile: 'mile',
  yard: 'yard',
  feet: 'feet',
} as const

export const MapMeasurementUnitArea = {
  squareMeter: 'squareMeter',
  squareKilometer: 'squareKilometer',
  squareMile: 'squareMile',
  squareFeet: 'squareFeet',
} as const

export const MapMeasurementUnitAuto = {
  'm-km': 'm-km',
  'ft-mi': 'ft-mi',
  ...MapMeasurementUnit,
} as const

export const MapMeasurementUnitTurf = {
  meters: 'meters',
  kilometer: 'kilometers',
  mile: 'miles',
} as const

export type MapMeasurementUnitAreaValue = Pick<
  typeof MapMeasurementUnit,
  'kilometer' | 'meter' | 'mile' | 'feet'
>

export const CONVERSIONS_UNITS: Record<
  ValueOf<typeof MapMeasurementUnit>,
  LengthUnits
> = {
  [MapMeasurementUnit.kilometer]: 'km',
  [MapMeasurementUnit.meter]: 'm',
  [MapMeasurementUnit.centimeter]: 'cm',
  [MapMeasurementUnit.milimeter]: 'mm',
  [MapMeasurementUnit.mile]: 'mi',
  [MapMeasurementUnit.yard]: 'yd',
  [MapMeasurementUnit.feet]: 'ft',
} as const

export const CONVERSIONS_UNITS_AREA: Record<
  ValueOf<typeof MapMeasurementUnitArea>,
  AreaUnits
> = {
  [MapMeasurementUnitArea.squareMeter]: 'm2',
  [MapMeasurementUnitArea.squareKilometer]: 'km2',
  [MapMeasurementUnitArea.squareMile]: 'mi2',
  [MapMeasurementUnitArea.squareFeet]: 'ft2',
} as const

export const CONVERSIONS_UNITS_FROM_LINEAR_TO_AREA: Record<
  keyof MapMeasurementUnitAreaValue,
  ValueOf<typeof MapMeasurementUnitArea>
> = {
  [MapMeasurementUnit.meter]: MapMeasurementUnitArea.squareMeter,
  [MapMeasurementUnit.kilometer]: MapMeasurementUnitArea.squareKilometer,
  [MapMeasurementUnit.mile]: MapMeasurementUnitArea.squareMile,
  [MapMeasurementUnit.feet]: MapMeasurementUnitArea.squareFeet,
} as const

export const INTL_UNITS: Record<ValueOf<typeof MapMeasurementUnit>, string> = {
  [MapMeasurementUnit.kilometer]: 'kilometer',
  [MapMeasurementUnit.meter]: 'meter',
  [MapMeasurementUnit.centimeter]: 'centimeter',
  [MapMeasurementUnit.milimeter]: 'millimeter',
  [MapMeasurementUnit.mile]: 'mile',
  [MapMeasurementUnit.yard]: 'yard',
  [MapMeasurementUnit.feet]: 'foot',
} as const

export const MEASUREMENT_TOOLS_UNITS_DISTANCE_VALUES: Record<
  MeasurementUnit,
  MeasurementUnitOption
> = {
  'm-km': {
    value: 'm-km',
    system: 'metric',
  },
  kilometer: {
    value: 'kilometer',
    system: 'metric',
  },
  meter: {
    value: 'meter',
    system: 'metric',
  },
  centimeter: {
    value: 'centimeter',
    system: 'metric',
  },
  milimeter: {
    value: 'milimeter',
    system: 'metric',
  },
  'ft-mi': {
    value: 'ft-mi',
    system: 'imperial',
  },
  mile: {
    value: 'mile',
    system: 'imperial',
  },
  yard: {
    value: 'yard',
    system: 'imperial',
  },
  feet: {
    value: 'feet',
    system: 'imperial',
  },
} as const

export const MEASUREMENT_TOOLS_UNITS_DISTANCE: MeasurementUnits<
  MeasurementMode,
  MeasurementUnit
>[keyof MeasurementModes] = [
  MEASUREMENT_TOOLS_UNITS_DISTANCE_VALUES['m-km'],
  MEASUREMENT_TOOLS_UNITS_DISTANCE_VALUES.kilometer,
  MEASUREMENT_TOOLS_UNITS_DISTANCE_VALUES.meter,
  MEASUREMENT_TOOLS_UNITS_DISTANCE_VALUES['ft-mi'],
  MEASUREMENT_TOOLS_UNITS_DISTANCE_VALUES.mile,
  MEASUREMENT_TOOLS_UNITS_DISTANCE_VALUES.feet,
] as const

export const MEASUREMENT_TOOLS_UNITS_AREA: MeasurementUnits<
  MeasurementMode,
  MeasurementUnit
>[keyof MeasurementModes] = [
  MEASUREMENT_TOOLS_UNITS_DISTANCE_VALUES['m-km'],
  MEASUREMENT_TOOLS_UNITS_DISTANCE_VALUES.kilometer,
  MEASUREMENT_TOOLS_UNITS_DISTANCE_VALUES.meter,
  MEASUREMENT_TOOLS_UNITS_DISTANCE_VALUES['ft-mi'],
  MEASUREMENT_TOOLS_UNITS_DISTANCE_VALUES.mile,
  MEASUREMENT_TOOLS_UNITS_DISTANCE_VALUES.feet,
] as const

export const DEFAULT_MEASUREMENT_TOOLS_MODES: MeasurementModes<
  MeasurementMode,
  GeoJsonEditMode
> = {
  distance: {
    value: 'distance',
    mode: CustomMeasureDistanceMode,
  },
  buffer: {
    value: 'buffer',
    mode: CustomMeasureBufferMode,
  },
  area: {
    value: 'area',
    mode: CustomMeasureAreaMode,
  },
} as const

export const DEFAULT_MEASUREMENT_TOOLS_UNITS: MeasurementUnits<
  MeasurementMode,
  MeasurementUnit
> = {
  distance: MEASUREMENT_TOOLS_UNITS_DISTANCE,
  buffer: MEASUREMENT_TOOLS_UNITS_DISTANCE,
  area: MEASUREMENT_TOOLS_UNITS_AREA,
} as const
