import { Paper, Flex, ScrollArea, Autocomplete, Title } from "@mantine/core";
import { ArticleCardVertical } from "./ArticleCard";
import Map, {
  Source,
  Layer,
  ScaleControl,
  GeolocateControl,
} from "react-map-gl/maplibre";
import 'maplibre-gl/dist/maplibre-gl.css';
import { useState, useEffect, useRef } from "react";
import Fuse from "fuse.js";

// import mapstyle from './assets/basemap.json';
import mapstyle from "./assets/basemap-mapbox.json";
import plus from "./assets/plus.png";
import minus from "./assets/minus.png";

import pin from "./assets/pin.png";
import prishvin from "./assets/prishvin.png";
import ostrovskiy from "./assets/ostrovskiy.png";
import brusov from "./assets/brusov.png";

export function KartaPage() {
  const mapRef = useRef(null);
  const [initial, setInitial] = useState(null);
  const [articles, setArticles] = useState(null);
  const [search, setSearch] = useState("");
  const [selected, setSelected] = useState(-1);
  const [cursor, setCursor] = useState("grab");

  const host = "https://strapi.litmusmap.ru";

  // Load icons
  const handleMapLoad = (e) => {
    const icons = ["pin", "prishvin", "ostrovskiy", "brusov"];
    const pinImage = new Image();
    pinImage.src = pin;
    pinImage.onload = () => mapRef.current.addImage("pin-marker", pinImage);
    const prishvinImage = new Image();
    prishvinImage.src = prishvin;
    prishvinImage.onload = () =>
      mapRef.current.addImage("prishvin-marker", prishvinImage);
    const ostrovskiyImage = new Image();
    ostrovskiyImage.src = ostrovskiy;
    ostrovskiyImage.onload = () =>
      mapRef.current.addImage("ostrovskiy-marker", ostrovskiyImage);
    const brusovImage = new Image();
    brusovImage.src = brusov;
    brusovImage.onload = () =>
      mapRef.current.addImage("brusov-marker", brusovImage);
  };

  // Load articles
  useEffect(() => {
    fetch(`${host}/api/articles?populate=*`)
      .then((r) => r.json())
      .then((d) => {
        setInitial(d.data);
        setArticles(d.data);
      });
  }, []);

  // Search
  const fuse =
    initial !== null &&
    new Fuse(initial, {
      keys: ["attributes.tags.value"],
    });

  useEffect(() => {
    const foundArticles = fuse && fuse.search(search).map((e) => e.item);
    const updatedArticles = search.length > 0 ? foundArticles : initial;
    setArticles(updatedArticles);
  }, [search]);

  // Select article interaction
  useEffect(() => {
    if (selected > 0) {
      const selectedArticleIndex = articles.findIndex((a) => a.id == selected);
      const selectedArticle = articles[selectedArticleIndex];
      const reorderedArticles = [
        selectedArticle,
        ...articles.filter((a) => a.id !== selected),
      ];
      setArticles(reorderedArticles);
      mapRef.current?.flyTo({
        center: [
          selectedArticle.attributes.longitude,
          selectedArticle.attributes.latitude,
        ],
        zoom: 10,
      });
    } else {
      mapRef.current?.flyTo({
        center: [35, 57],
        zoom: 5,
      });
    }
  }, [selected]);

  const handleAddressClick = (id) => {
    setSelected(id);
  };

  // Zoom
  const ZoomControl = (props) => {
    const zoomIn = () => {
      mapRef.current.zoomTo(mapRef.current.getZoom() + 1);
    };
    const zoomOut = () => {
      mapRef.current.zoomTo(mapRef.current.getZoom() - 1);
    };
    return (
      <Flex
        style={{
          position: "absolute",
          bottom: props.bottom,
          right: props.right,
        }}
      >
        <Paper
          onClick={zoomOut}
          radius="xl"
          bg={"none"}
          sx={{ "&:hover": { backgroundColor: "white", cursor: "pointer" } }}
          maw={48}
          mah={48}
        >
          <img src={minus} style={{ width: "48px", height: "48px" }}></img>
        </Paper>
        <Paper
          onClick={zoomIn}
          radius="xl"
          bg={"none"}
          sx={{ "&:hover": { backgroundColor: "white", cursor: "pointer" } }}
          maw={48}
          mah={48}
        >
          <img src={plus} style={{ width: "48px", height: "48px" }}></img>
        </Paper>
      </Flex>
    );
  };

  return (
    <div style={{ position: "relative" }}>
      <Map
        ref={mapRef}
        initialViewState={{
          longitude: 30,
          latitude: 60,
          zoom: 4,
        }}
        minZoom={3.5}
        maxZoom={16}
        maxBounds={[
          [-20, 35],
          [200, 80],
        ]}
        style={{
          height: "90vh",
        }}
        cursor={cursor}
        mapStyle={mapstyle}
        interactiveLayerIds={["points-layer"]}
        onClick={(e) => {
          // console.log(e.features);
          e.features[0]
            ? (setSelected(e.features[0].properties.id),
              mapRef.current.flyTo({
                center: e.features[0].geometry.coordinates,
                zoom: mapRef.current.getZoom() + 6,
              }))
            : setSelected(-1);
        }}
        onMouseEnter={() => setCursor("pointer")}
        onMouseLeave={() => setCursor("grab")}
        onLoad={handleMapLoad}
      >
        <Source
          id="points"
          type="vector"
          tiles={[`${host}/tiles/{z}/{x}/{y}.pbf`]}
          maxzoom={10}
        >
          <Layer
            id="points-layer"
            type="circle"
            source-layer="layer"
            filter={
              articles === null || articles.length == 0
                ? false
                : ["in", "id", ...articles.map((a) => a.id)]
            }
            paint={{
              "circle-color": [
                "match",
                ["get", "id"],
                selected,
                "#e66a5a",
                "#F2994A",
              ],
              "circle-radius": 8,
              "circle-opacity": ["step", ["zoom"], 0.8, 7, 0],
            }}
          />
          <Layer
            id="icons-layer"
            type="symbol"
            source-layer="layer"
            filter={
              articles === null || articles.length == 0
                ? false
                : ["in", "id", ...articles.map((a) => a.id)]
            }
            layout={{
              "icon-image": "pin-marker",
              "icon-size": ['interpolate', ['linear'], ['zoom'], 7, 0.5, 12, 1],
            }}
            minzoom={7}
            maxzoom={12}
          />
          <Layer
            id="portret-layer"
            type="symbol"
            source-layer="layer"
            filter={
              articles === null || articles.length == 0
                ? false
                : ["in", "id", ...articles.map((a) => a.id)]
            }
            layout={{
              "icon-image": [
                "match",
                ["get", "id"],
                6,
                "ostrovskiy-marker",
                7,
                "brusov-marker",
                1,
                "prishvin-marker",
                "pin-marker",
              ],
              "icon-size": ['interpolate', ['linear'], ['zoom'], 12, 0.05, 14, 0.1],
            }}
            minzoom={12}
          />
        </Source>
        <ScaleControl position="bottom-right" />
        <ZoomControl bottom="35px" right="4px" />
        <GeolocateControl
          showAccuracyCircle={false}
          position="bottom-right"
          style={{
            marginBottom: "55px",
            marginRight: "14px",
            background: "none",
            boxShadow: "none",
          }}
        />
      </Map>

      <Paper
        shadow={"md"}
        withBorder
        style={{
          position: "absolute",
          top: "1rem",
          left: "1rem",
          width: "36rem",
          height: "83vh",
          opacity: "95%",
          padding: "1rem 0 1rem 1rem",
        }}
      >
        <Title order={3} mb={10}>
          Статьи
        </Title>
        <Autocomplete
          mr={20}
          mb={30}
          placeholder="Поиск"
          limit={2}
          value={search}
          onChange={setSearch}
          data={[]}
        />
        <ScrollArea h={"67vh"} type="auto">
          <Flex
            mih={50}
            gap="md"
            justify="flex-start"
            align="start"
            direction="column"
            wrap="wrap"
            mr={20}
          >
            {articles !== null &&
              articles.length > 0 &&
              articles.map((article) => (
                <ArticleCardVertical
                  key={article.id}
                  id={article.id}
                  image={
                    article.attributes.cover.data !== null
                      ? host + article.attributes.cover.data.attributes.url
                      : ""
                  }
                  category="музеи"
                  title={article.attributes.title}
                  address={article.attributes.address}
                  longitude={article.attributes.longitude}
                  latitude={article.attributes.latitude}
                  selected={selected}
                  clickAddressAction={handleAddressClick}
                />
              ))}
          </Flex>
        </ScrollArea>
      </Paper>
    </div>
  );
}
