'use client'

import * as React from 'react'
import { scaleLinear } from 'd3-scale'
import {
  ComposableMap,
  Geographies,
  Geography,
  Marker,
  ZoomableGroup,
} from 'react-simple-maps'
import ReactTooltip from 'react-tooltip'
import { CircularProgress } from '@mui/material'
import { useTheme } from '@mui/material/styles'
import { ApiState, CountryDataResponse } from '../typeDefs/explorer-api'
import MAP_TOPOJSON from '../assets/world-110m.json'

type MapProps = {
  userLocation?: [number, number]
  countryData?: ApiState<CountryDataResponse>
  loading: boolean
}

export const WorldMap: FCWithChildren<MapProps> = ({
  countryData,
  userLocation,
  loading,
}) => {
  const { palette } = useTheme()

  const colorScale = React.useMemo(() => {
    if (countryData?.data) {
      const heighestNumberOfNodes = Math.max(
        ...Object.values(countryData.data).map((country) => country.nodes)
      )
      return scaleLinear<string, string>()
        .domain([
          0,
          1,
          heighestNumberOfNodes / 4,
          heighestNumberOfNodes / 2,
          heighestNumberOfNodes,
        ])
        .range(palette.nym.networkExplorer.map.fills)
        .unknown(palette.nym.networkExplorer.map.fills[0])
    }
    return () => palette.nym.networkExplorer.map.fills[0]
  }, [countryData, palette])

  const [tooltipContent, setTooltipContent] = React.useState<string | null>(
    null
  )

  if (loading) {
    return <CircularProgress />
  }

  return (
    <>
      <ComposableMap
        data-tip=""
        style={{
          backgroundColor: palette.nym.networkExplorer.background.tertiary,
          width: '100%',
          height: 'auto',
        }}
        viewBox="0, 50, 800, 350"
        projection="geoMercator"
        projectionConfig={{
          scale: userLocation ? 200 : 100,
          center: userLocation,
        }}
      >
        <ZoomableGroup>
          <Geographies geography={MAP_TOPOJSON}>
            {({ geographies }) =>
              geographies.map((geo) => {
                const d = (countryData?.data || {})[geo.properties.ISO_A3]
                return (
                  <Geography
                    key={geo.rsmKey}
                    geography={geo}
                    fill={colorScale(d?.nodes || 0)}
                    stroke={palette.nym.networkExplorer.map.stroke}
                    strokeWidth={0.2}
                    onMouseEnter={() => {
                      const { NAME_LONG } = geo.properties
                      if (!userLocation) {
                        setTooltipContent(`${NAME_LONG} | ${d?.nodes || 0}`)
                      }
                    }}
                    onMouseLeave={() => {
                      setTooltipContent('')
                    }}
                    style={{
                      hover:
                        !userLocation && countryData
                          ? {
                              fill: palette.nym.highlight,
                              outline: 'white',
                            }
                          : undefined,
                    }}
                  />
                )
              })
            }
          </Geographies>

          {userLocation && (
            <Marker coordinates={userLocation}>
              <g
                fill="grey"
                stroke="#FF5533"
                strokeWidth="2"
                strokeLinecap="round"
                strokeLinejoin="round"
                transform="translate(-12, -10)"
              >
                <circle cx="12" cy="10" r="5" />
              </g>
            </Marker>
          )}
        </ZoomableGroup>
      </ComposableMap>
      <ReactTooltip>{tooltipContent}</ReactTooltip>
    </>
  )
}
