import React, { FC, ReactElement, useState } from 'react'
import MunicipalitySearch, {
  Municipality,
} from '@ta-interaktiv/react-municipality-search'
import ChoroplethMap from './choroplethMap'
import { ToolTipProps } from '../types/toolTipProps'

export interface SwissMapProps<T> {
  /** The actual data to color the map. */
  municipalityData: T[]
  /** The key of the property you want to compare over the municipalities (e.g. "taxBurden") */
  propertyNameToCompare?: keyof T
  /** The name of the property that contains the unique identifier for each municipality (e.g. "bfsId") */
  idPropertyName?: keyof T
  /** A function that returns the value of the property you want to compare. Useful if you have nested data that you want to display */
  customValueAccessFunction?: (
    municipalityId: number | string | undefined,
    municipalityData: T[],
  ) => number | string | undefined | null
  /** Hide the search bar */
  hideMunicipalitySearch?: boolean
  /** The lowest value of your municipalityData  */
  minValue: number
  /** The highest value of your municipalityData  */
  maxValue: number
  /** A function that returns a color for a value. The value will be passed to the function (e.g. (value) => {return value < 5 ? "green" : "red"}) */
  colorFunction?: (value: any) => string
  /** The dataset used for the municipality search bar. Go to https://atm-municipality-search.s3.eu-west-1.amazonaws.com/index.html to see the available datasets (e.g. "2020") */
  municipalitySearchYear?: string
  /** The placeholder of the municipality search bar default is 'Gemeindesuche' and 'Nom de la commune' */
  municipalitySearchPlaceholder?: string
  /** Pass a custom array of municipalities for the municipality search */
  municipalitySearchCustomMunicipalities?: Municipality[]
  /** The year of the topoJson that will be fetched and used to draw the map. Go to https://swiss-maps.vercel.app/ to see the available datasets */
  topoJsonYear: number
  /** If you want to use your own (local) topoJson you can pass it here. Go to https://swiss-maps.vercel.app/ to see the available datasets */
  topoJson?: any
  /** The name of the object in the topoJson that contains the municipalities. Default is "municipalities" */
  topoJsonObjectName?: string
  /** This function gets triggered when a new municipality is selected. The bfsId will be passed to the function (e.g. 261) */
  newActiveMunicipalityIdHandler?: (newId?: number) => void
  /** The bfsId of the active municipality */
  activeMunicipalityId?: number
  /** This function gets triggered when the mouse hovers over a municipality. The municipalityData object of the currently hovered municipality will be passed to the function (e.g. {bfsId: 261, taxBurden: "7"}) */
  hoverHandler?: (newData: T) => void
  /** show the zoom controls */
  isZoomable?: boolean
  /** zoom to the currently selected municipality */
  zoomIntoActiveMunicipality?: boolean
  /** distance to the zoomed in municipality */
  zoomDistance?: number
  /** event handler for fullscreen state change */
  fullscreenChangeHandler?: (isFullscreen: boolean) => void
  /** is the map in fullscreen mode or not */
  isFullscreen?: boolean
  /** hint text for the fullscreen button */
  fullscreenHint?: string
  /** disable touch events on 600px width or smaller */
  disableTouchOnMobile?: boolean
  /** To show a tooltip when hovering you need to pass a tooltip component. The municipalityData object of the currently hovered municipality will be passed as a prop (e.g. {bfsId: 261, taxBurden: "7"}) */
  ToolTip?: FC<ToolTipProps>
  /** The colorpalette of 3 colors (low, mid, high) for the choropleth map. You can use color names or hex (e.g. ['green', 'lightgrey', '#ff0000']) */
  colorPalette?: [string, string, string]
  /** stroke-width of active municipality */
  activeStrokeWidth?: string
  /** stroke-color of active municipality */
  activeStrokeColor?: string
  /** stroke-width of hovered municipality */
  hoverStrokeWidth?: string
  /** stroke-color of hovered municipality */
  hoverStrokeColor?: string
  /** stroke-color of all municipalities */
  municipalityStrokeColor?: string
  /** stroke-width of all municipalities */
  municipalityStrokeWidth?: string
  /** fallback fill for municipalities with no data */
  municipalityFallbackFillColor?: string
  /** fill of all lakes */
  lakeFillColor?: string
  /** stroke-color of all lakes */
  lakeStrokeColor?: string
  /** stroke-width of all lakes */
  lakeStrokeWidth?: string
  /** stroke-color national border */
  nationalBorderColor?: string
  /** stroke-width national border */
  nationalBorderWidth?: string
  /** stroke-color of all cantons */
  cantonStrokeColor?: string
  /** stroke-width of all cantons */
  cantonStrokeWidth?: string
  /** lang of component */
  locale?: 'de' | 'fr'
}

export const SwissMap = <T,>({
  municipalityData,
  propertyNameToCompare,
  idPropertyName,
  customValueAccessFunction,
  hideMunicipalitySearch,
  minValue,
  maxValue,
  municipalitySearchYear,
  municipalitySearchPlaceholder,
  municipalitySearchCustomMunicipalities,
  topoJsonYear,
  topoJson,
  topoJsonObjectName,
  newActiveMunicipalityIdHandler,
  activeMunicipalityId,
  hoverHandler,
  isZoomable,
  zoomIntoActiveMunicipality,
  zoomDistance,
  fullscreenChangeHandler,
  isFullscreen,
  fullscreenHint,
  disableTouchOnMobile,
  ToolTip,
  colorPalette,
  colorFunction,
  activeStrokeWidth,
  activeStrokeColor,
  hoverStrokeWidth,
  hoverStrokeColor,
  municipalityStrokeColor,
  municipalityStrokeWidth,
  municipalityFallbackFillColor,
  lakeFillColor,
  lakeStrokeColor,
  lakeStrokeWidth,
  nationalBorderColor,
  nationalBorderWidth,
  cantonStrokeColor,
  cantonStrokeWidth,
  locale,
}: SwissMapProps<T>) => {
  const [toolTipData, setToolTipData] = useState<any | null>()
  // toolTipRef
  const toolTipRef = React.useRef<HTMLDivElement>(null)
  const toolTipStyle = {
    pointerEvents: 'none' as 'none',
    position: 'fixed' as 'fixed',
    opacity: 0,
    transition: 'opacity 0.3s ease-in-out',
    zIndex: 100,
  }
  return (
    <div>
      {!hideMunicipalitySearch && municipalitySearchYear && (
        <MunicipalitySearch
          municipalityData={municipalitySearchYear}
          locale={locale}
          dedupe
          resetOnSelect
          selectedMunicipalityId={activeMunicipalityId}
          placeholder={
            municipalitySearchPlaceholder ??
            (locale === 'fr' ? 'Nom de la commune' : 'Gemeindesuche')
          }
          customMunicipalities={municipalitySearchCustomMunicipalities}
          onSelectionHandler={(selectedMunicipality: Municipality) => {
            if (newActiveMunicipalityIdHandler) {
              newActiveMunicipalityIdHandler(selectedMunicipality.GDENR)
            }
          }}
          onCloseHandler={() => {
            if (newActiveMunicipalityIdHandler) {
              newActiveMunicipalityIdHandler(undefined)
            }
          }}
        />
      )}
      <ChoroplethMap
        municipalityData={municipalityData}
        propertyNameToCompare={propertyNameToCompare}
        customValueAccessFunction={customValueAccessFunction}
        idPropertyName={idPropertyName}
        minValue={minValue}
        maxValue={maxValue}
        topoJsonYear={topoJsonYear}
        topoJson={topoJson}
        topoJsonObjectName={topoJsonObjectName}
        activeMunicipalityId={activeMunicipalityId}
        newActiveMunicipalityIdHandler={(newId) => {
          if (newActiveMunicipalityIdHandler) {
            newActiveMunicipalityIdHandler(newId)
          }
        }}
        hoverHandler={(newData) => {
          if (hoverHandler) {
            hoverHandler(newData)
          }
          if (ToolTip) {
            setToolTipData(newData)
          }
        }}
        isZoomable={isZoomable}
        zoomIntoActiveMunicipality={zoomIntoActiveMunicipality}
        zoomDistance={zoomDistance}
        fullscreenChangeHandler={fullscreenChangeHandler}
        isFullscreen={isFullscreen}
        fullscreenHint={fullscreenHint}
        disableTouchOnMobile={disableTouchOnMobile}
        colorPalette={colorPalette}
        colorFunction={colorFunction}
        activeStrokeWidth={activeStrokeWidth}
        activeStrokeColor={activeStrokeColor}
        hoverStrokeWidth={hoverStrokeWidth}
        hoverStrokeColor={hoverStrokeColor}
        municipalityStrokeColor={municipalityStrokeColor}
        municipalityStrokeWidth={municipalityStrokeWidth}
        lakeFillColor={lakeFillColor}
        lakeStrokeColor={lakeStrokeColor}
        lakeStrokeWidth={lakeStrokeWidth}
        nationalBorderColor={nationalBorderColor}
        nationalBorderWidth={nationalBorderWidth}
        cantonStrokeColor={cantonStrokeColor}
        cantonStrokeWidth={cantonStrokeWidth}
        toolTipRef={toolTipRef}
        municipalityFallbackFillColor={municipalityFallbackFillColor}
      />
      {ToolTip && (
        <div id='tooltip' style={toolTipStyle} ref={toolTipRef}>
          <ToolTip activeData={toolTipData} locale={locale} />
        </div>
      )}
    </div>
  )
}
