// ---------------------------------------------------------------------------------------------------------------------
//!                                                      Imports
// ---------------------------------------------------------------------------------------------------------------------

// -------------------------------------------------- React & Next -----------------------------------------------------
import { useEffect, useRef, useState } from 'react';
// ---------------------------------------------------------------------------------------------------------------------

// --------------------------------------------------- Components ------------------------------------------------------
import { IconLayer, ScatterplotLayer } from 'deck.gl';
// ---------------------------------------------------------------------------------------------------------------------

// ------------------------------------------------- Assets & Styles ---------------------------------------------------
import { StringifiedPinIcon } from '@/assets/PinIcon';
import { getDataset } from '../request';
// ---------------------------------------------------------------------------------------------------------------------

export const useData = () => {
	const deckRef = useRef(null);

	const [canUseGeolocation, setCanUseGeolocation] = useState<boolean>(false);
	const [geoError, setGeoError] = useState<string | null>(null);
	const [userLocation, setUserLocation] = useState<{ [key: string]: number }>(
		{}
	);

	const [source, setSource] = useState([]);
	const [layers, setLayers] = useState([]);

	const [isAddLoveOpened, setIsAddLoveOpened] = useState<boolean>(false);
	const [isLoading, setIsLoading] = useState<boolean>(false);
	const [addLoveMessage, setAddLoveMessage] = useState<string | null>(null);

	const [viewState, setViewState] = useState<any>({
		longitude: 2.209666999999996,
		latitude: 46.232192999999995,
		zoom: 5,
	});

	useEffect(() => {
		if ('geolocation' in navigator == false) {
			setCanUseGeolocation(false);
			return;
		}

		setCanUseGeolocation(true);

		navigator.geolocation.getCurrentPosition(
			(position) => {
				setViewState((prev) => ({
					...prev,
					latitude: position.coords.latitude,
					longitude: position.coords.longitude,
					zoom: 17,
				}));
				setUserLocation({
					latitude: position.coords.latitude,
					longitude: position.coords.longitude,
				});
			},
			(error) => {
				console.warn(error.message);
				if (error.PERMISSION_DENIED) {
					setGeoError('permission_denied');
				}
			},
			{
				maximumAge: 0,
				timeout: 5000,
				enableHighAccuracy: true,
			}
		);

		(async () => {
			const dataset = await getDataset();

			const formattedDataset = dataset.map((point) => {
				const properties = { ...point };
				delete properties.geopoint;

				return {
					type: 'Feature',
					geometry: point.geopoint,
					properties: properties,
				};
			});

			setSource(formattedDataset);
		})();
	}, []);

	useEffect(() => {
		const newLayers = [];

		if (userLocation) {
			const userLayer = new ScatterplotLayer({
				id: 'userLayer',
				data: [userLocation],
				stroked: true,
				getPosition: (d) => [d.longitude, d.latitude],
				getRadius: 10,
				getFillColor: [217, 66, 83],
				getLineColor: [217, 66, 83, 175],
				getLineWidth: 5,
				radiusUnits: 'pixels',
				lineWidthUnits: 'pixels',
				pickable: false,
			});

			newLayers.push(userLayer);
		}

		const datasetLayer = new IconLayer({
			id: 'lovePoints',
			data: source,
			iconAtlas: `data:image/svg+xml;charset=utf-8,${encodeURIComponent(
				StringifiedPinIcon()
			)}`,
			iconMapping: {
				marker: {
					x: 0,
					y: 0,
					width: 100,
					height: 100,
					anchorY: 100,
				},
			},
			getIcon: (d) => 'marker',
			getSize: (d) => 35,
			getPosition: (d) => d.geometry.coordinates,
			billboard: true,
			pickable: true,
		});

		newLayers.push(datasetLayer);
		setLayers(newLayers);
	}, [userLocation, source, isAddLoveOpened]);

	return {
		deckRef,
		viewState,
		setViewState,
		geoError,
		layers,
		canUseGeolocation,
		isAddLoveOpened,
		setIsAddLoveOpened,
		isLoading,
		setIsLoading,
		addLoveMessage,
		setAddLoveMessage,
	};
};
