import { useEffect, useRef, useState } from 'react';
import { useMediaQuery } from 'react-responsive';

import ArcGISMap from '@arcgis/core/Map';
import Extent from '@arcgis/core/geometry/Extent';
import MapView from '@arcgis/core/views/MapView';
import Basemap from '@arcgis/core/Basemap';
import MapImageLayer from '@arcgis/core/layers/MapImageLayer';
import WMTSLayer from '@arcgis/core/layers/WMTSLayer';
import SpatialReference from '@arcgis/core/geometry/SpatialReference';
import Search from '@arcgis/core/widgets/Search';
import ScaleBar from '@arcgis/core/widgets/ScaleBar';
import GraphicsLayer from '@arcgis/core/layers/GraphicsLayer';
import Graphic from '@arcgis/core/Graphic';
import LayerList from '@arcgis/core/widgets/LayerList';
import Zoom from '@arcgis/core/widgets/Zoom';
import Legend from '@arcgis/core/widgets/Legend';
import FeatureLayer from '@arcgis/core/layers/FeatureLayer';
import Polygon from '@arcgis/core/geometry/Polygon';
import esriConfig from '@arcgis/core/config';
import { watch } from '@arcgis/core/core/reactiveUtils';
import SimpleFillSymbol from '@arcgis/core/symbols/SimpleFillSymbol';

import './esri-ui-grundlagenkarte.css';
import { Vienna, Austria } from '@/public/borders-vienna-austria';
import { BASEMAP_AT_URL, AMPEL_GWWP_URL, RESOURCES_GWWP_URL, SRS } from '@/app/config/config';
import getAddress from '@/app/utils/getAddress';
import identifyAllLayers from '@/app/utils/identify';
import takeScreenshot from '@/app/utils/screenshot';
import { useAppDispatch } from '@/redux/hooks';

import PanelGrundlagenkarte from './panel-grundlagenkarte-gwwp';

// set path for local assets
esriConfig.assetsPath = '/assets';

export default function MapComponent() {
  const dispatch = useAppDispatch();
  const isMobile = useMediaQuery({ maxWidth: 480 });

  const mapDiv = useRef<HTMLDivElement | null>(null);
  const [address, setAddress] = useState<string[]>([]);

  useEffect(() => {
    let view: MapView;
    let handle: IHandle;
    if (mapDiv.current) {
      view = new MapView({
        container: mapDiv.current,
        extent: new Extent({
          xmin: -19000,
          ymin: 325000,
          xmax: 29000,
          ymax: 360000,
          spatialReference: new SpatialReference({ wkid: SRS }),
        }),
        popupEnabled: false,
      });

      let viennaGraphic = new Graphic({
        geometry: new Polygon({ rings: [Austria, Vienna], spatialReference: { wkid: SRS } }),
        symbol: {
          type: 'simple-fill',
          color: [209, 213, 219, 0.65],
          style: 'solid',
          outline: {
            color: 'white',
            width: 0,
          },
        } as unknown as SimpleFillSymbol,
      });

      // graphic layers
      let viennaGraphicsLayer = new GraphicsLayer({ title: 'Wien', listMode: 'hide' });
      viennaGraphicsLayer.add(viennaGraphic);

      const ampelkarte_gwwp = new FeatureLayer({
        url: AMPEL_GWWP_URL + '/0',
        title: 'Mögliche Einschränkungen',
        visible: false,
        listMode: 'show',
        opacity: 0.5,
      });

      const resources_gwwp = new MapImageLayer({
        title: 'Ressourcen',
        url: RESOURCES_GWWP_URL,
        visible: false,
        listMode: 'show',
        opacity: 0.5,
      });

      // basemap in Viennese coordinate system due to tranformation inaccuracies from MGI to WGS84
      // default transformation in ArcGIS API from MGI to WGS84 is 1306
      // transformation 1618 is recommended
      const basemap_at = new WMTSLayer({
        url: BASEMAP_AT_URL,
        listMode: 'hide',
      });

      let basemap = new Basemap({
        baseLayers: [basemap_at],
        title: 'basemap.at',
        id: 'basemap.at',
        spatialReference: { wkid: SRS },
      });

      let arcgisMap = new ArcGISMap({
        basemap: basemap,
        layers: [resources_gwwp, ampelkarte_gwwp, viennaGraphicsLayer],
      });

      const layerList = new LayerList({
        view,
      });

      const search = new Search({
        view,
        popupEnabled: true,
      });

      const scaleBar = new ScaleBar({
        view: view,
        unit: 'metric',
      });

      const zoom = new Zoom({
        view,
        layout: 'horizontal',
      });

      const legend = new Legend({
        view,
      });

      // register event handler for mouse clicks
      view.on('immediate-click', (event) => {
        if (setAddress) {
          takeScreenshot(view, event.mapPoint, dispatch, true);
          getAddress(event.mapPoint, setAddress);
          identifyAllLayers(view, event.mapPoint, dispatch, 'GWWP');
        }
      });

      // add map to view
      view.map = arcgisMap;

      // add UI components
      view.ui.components = [];
      if (!isMobile) {
        view.ui.add([zoom, search, layerList], 'top-left');
        view.ui.add(scaleBar, 'bottom-left');
      }

      view.when(() => {
        handle = watch(
          () => view.map?.layers?.map((layer) => layer.visible),
          () => {
            if (view.map?.layers?.some((layer) => layer.title !== 'Wien' && layer.visible === true)) {
              view.ui?.add(legend, 'top-left');
            } else {
              view.ui?.remove(legend);
            }
          }
        );
      });
    }

    return () => {
      handle?.remove();
      view?.destroy();
    };
  }, [dispatch, isMobile]);

  return (
    <div ref={mapDiv} className="absolute top-16 bottom-0 w-full">
      <PanelGrundlagenkarte address={address}></PanelGrundlagenkarte>
    </div>
  );
}
