import { Paper, Flex, ScrollArea, Autocomplete, Title } from "@mantine/core";
import { useDisclosure } from "@mantine/hooks";
import { HeaderSimple } from "./Header";
import { FooterLinks } from "./Footer";
import headerLinks from "./assets/header.json";
import footerLinks from "./assets/footer.json";
import { ArticleCardVertical } from "./ArticleCard";
import { ArticleCardMobile } from "./ArticleCardMobile";
import Map, {
  Source,
  Layer,
  ScaleControl,
  GeolocateControl,
  Popup,
} 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";

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

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

  const roundImage = (img) => {
    const imgSize = img.width;
    // const strokeWidth = 4;
    // Create a canvas element
    const canvas = document.createElement("canvas");
    const ctx = canvas.getContext("2d");

    const radius = imgSize / 2;
    canvas.width = imgSize;
    canvas.height = imgSize;

    // Create a clipping path in the shape of a circle
    ctx.beginPath();
    ctx.arc(radius, radius, radius, 0, 2 * Math.PI);
    ctx.closePath();
    ctx.clip();

    ctx.drawImage(img, 0, 0, imgSize, imgSize);

    // Apply a border by drawing a circle with a larger radius and stroke it
    // ctx.lineWidth = strokeWidth;
    // ctx.strokeStyle = "white";
    // ctx.stroke();

    const modifiedImage = canvas.toDataURL(); // Get the modified image as a data URL
    return modifiedImage;
  };

  // Load icons
  const handleMapLoad = () => {
    const pinImage = new Image();
    pinImage.src = pin;
    pinImage.onload = () => mapRef.current.addImage("pin-marker", pinImage);

    const markers = initial.map((article) => ({
      markerName: `marker-${article.id}`,
      markerUrl: `${host}${article.attributes.marker.data.attributes.formats.thumbnail.url}`,
    }));
    markers.map((m) => {
      const markerImage = new Image(100, 100);
      markerImage.crossOrigin = "Anonymous"; // https://stackoverflow.com/questions/22097747/how-to-fix-getimagedata-error-the-canvas-has-been-tainted-by-cross-origin-data
      markerImage.onload = () => {
        const markerImageRounded = new Image();
        markerImageRounded.src = roundImage(markerImage);
        markerImageRounded.onload = () => {
          mapRef.current.addImage(m.markerName, markerImageRounded);
        };
      };
      markerImage.src = m.markerUrl;
    });
  };

  // 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 (
    <>
      <HeaderSimple
        links={headerLinks.links}
        openedMenuKarta={openedMenu}
        menuactionskarta={menuactions}
      />
      <div style={{ position: "relative" }}>
        <Map
          ref={mapRef}
          initialViewState={{
            longitude: 35,
            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);
            if (e.features[0]) {
              setSelected(e.features[0].properties.id);
              if (mapRef.current.getZoom() < 14) {
                mapRef.current.flyTo({
                  center: e.features[0].geometry.coordinates,
                  zoom: mapRef.current.getZoom() + 6,
                });
              } else {
                setPopupInfo({
                  longitude: e.features[0].geometry.coordinates[0],
                  latitude: e.features[0].geometry.coordinates[1],
                  id: e.features[0].properties.id,
                });
              }
            } else {
              setSelected(-1);
            }
          }}
          onMouseEnter={() => setCursor("pointer")}
          onMouseLeave={() => setCursor("grab")}
          onLoad={handleMapLoad}
        >
          <Source
            id="points"
            type="vector"
            tiles={[`${host}/tiles/{z}/{x}/{y}.pbf`]}
            maxzoom={10}
          >
            {popupInfo && (
              <Popup
                key={popupInfo.id}
                longitude={popupInfo.longitude}
                latitude={popupInfo.latitude}
                anchor="top"
                closeButton={false}
                onClose={() => setPopupInfo(null)}
                offset={30}
              >
                <a href={`/article/${popupInfo.id}`}>подробнее</a>
              </Popup>
            )}
            <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": ["step", ["zoom"], 8, 7, 20, 12, 40, 14, 60],
                "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.4,
                  12,
                  0.8,
                ],
              }}
              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": ["concat", "marker-", ["get", "id"]],
                "icon-size": [
                  "interpolate",
                  ["linear"],
                  ["zoom"],
                  12,
                  0.4,
                  14,
                  0.8,
                ],
              }}
              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>

        {/* Search mobile */}
        <Paper
          shadow={"md"}
          radius={0}
          display={!openedMenu && "none"}
          style={{
            position: "absolute",
            top: 0,
            left: 0,
            right: 0,
            height: "340px",
            opacity: "95%",
            padding: "55px 0 1rem 1rem",
          }}
          sx={{
            "@media (min-width: 60em)": {
              display: "none",
            },
          }}
        >
          <Autocomplete
            mr={20}
            mb={10}
            placeholder="Поиск"
            limit={2}
            value={search}
            onChange={setSearch}
            data={[]}
          />
          <ScrollArea h={"225px"} type="auto">
            <Flex
              // mih={50}
              gap="xs"
              justify="flex-start"
              align="start"
              direction="column"
              wrap="wrap"
              mr={20}
            >
              {articles !== null &&
                articles.length > 0 &&
                articles.map((article) => (
                  <ArticleCardMobile
                    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>

        {/* Search pc */}
        <Paper
          shadow={"md"}
          withBorder
          style={{
            position: "absolute",
            top: "1rem",
            left: "1rem",
            width: "36rem",
            height: "80%",
            opacity: "95%",
            padding: "1rem 0 1rem 1rem",
          }}
          sx={{
            "@media (max-width: 60em)": {
              display: "none",
            },
          }}
        >
          <Title order={3} mb={10}>
            Музеи
          </Title>
          <Autocomplete
            mr={20}
            mb={30}
            placeholder="Поиск"
            limit={2}
            value={search}
            onChange={setSearch}
            data={[]}
          />
          <ScrollArea
            h={"80%"}
            type="auto"
            sx={{
              "@media (max-height: 700px)": {
                height: "60%",
              },
              "@media (max-height: 400px)": {
                height: "50%",
              },
            }}
          >
            <Flex
              mih="40rem"
              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>
      <FooterLinks data={footerLinks.data} />
    </>
  );
}
