import * as React from 'react'
import { Marker, Tooltip, useMap, useMapEvents } from 'react-leaflet'
import { Item, LayerProps, Tag } from '../../types'
import MarkerIconFactory from '../../Utils/MarkerIconFactory'
import { ItemViewPopup } from './Subcomponents/ItemViewPopup'
import { useItems, useSetItemsApi, useSetItemsData } from './hooks/useItems'
import { useEffect, useState } from 'react'
import { ItemFormPopup } from './Subcomponents/ItemFormPopup'
import { useFilterTags, useIsLayerVisible } from './hooks/useFilter'
import { useAddTag, useAllTagsLoaded, useGetItemTags, useTags } from './hooks/useTags'
import { useAddMarker, useAddPopup, useLeafletRefs } from './hooks/useLeafletRefs'
import { Popup } from 'leaflet'
import { useLocation } from 'react-router-dom';
import { getValue } from '../../Utils/GetValue'
import { hashTagRegex } from '../../Utils/HashTagRegex'
import { randomColor } from '../../Utils/RandomColor'

export const Layer = ({
    data,
    children,
    name = 'places',
    menuIcon = 'MapPinIcon',
    menuText = 'add new place',
    menuColor = '#2E7D32',
    markerIcon = 'circle-solid',
    markerShape = 'circle',
    markerDefaultColor = '#777',
    api,
    itemNameField = 'name',
    itemTextField = 'text',
    itemAvatarField,
    itemColorField,
    itemOwnerField,
    itemLatitudeField = 'position.coordinates.1',
    itemLongitudeField = 'position.coordinates.0',
    onlyOnePerOwner = false,
    setItemFormPopup,
    itemFormPopup,
    clusterRef
}: LayerProps) => {

    const filterTags = useFilterTags();

    const items = useItems();
    const setItemsApi = useSetItemsApi();
    const setItemsData = useSetItemsData();
    const getItemTags = useGetItemTags();
    const addMarker = useAddMarker();
    const addPopup = useAddPopup();
    const leafletRefs = useLeafletRefs();

    let location = useLocation();

    const allTagsLoaded = useAllTagsLoaded();
    const tags = useTags();
    const addTag = useAddTag();
    const [newTagsToAdd, setNewTagsToAdd] = useState<Tag[]>([]);
    const [tagsReady, setTagsReady] = useState<boolean>(false);


    const map = useMap();

    const isLayerVisible = useIsLayerVisible();


    useEffect(() => {
        data && setItemsData({ data, children, name, menuIcon, menuText, menuColor, markerIcon, markerShape, markerDefaultColor, api, itemNameField, itemTextField, itemAvatarField, itemColorField, itemOwnerField, onlyOnePerOwner, setItemFormPopup, itemFormPopup, clusterRef });
        api && setItemsApi({ data, children, name, menuIcon, menuText, menuColor, markerIcon, markerShape, markerDefaultColor, api, itemNameField, itemTextField, itemAvatarField, itemColorField, itemOwnerField, onlyOnePerOwner, setItemFormPopup, itemFormPopup, clusterRef });
    }, [data, api])

    useMapEvents({
        popupopen: (e) => {
            const item = Object.entries(leafletRefs).find(r => r[1].popup == e.popup)?.[1].item;
            if (item?.layer?.name == name && window.location.pathname.split("/")[2] != item.id) {
                window.history.pushState({}, "", `/${name}/${item.id}`)
                let title = "";
                if (item.name) title = item.name;
                else if (item.layer?.itemNameField) title = getValue(item, item.layer.itemNameField);
                document.title = `${document.title.split("-")[0]} - ${title}`;
            }
        },
    })

    const openPopup = () => {
        if (window.location.pathname.split("/").length <= 2 || window.location.pathname.split("/")[2] === "") {
            map.closePopup();
        }
        else {
            if (window.location.pathname.split("/")[1] == name) {

                if (window.location.pathname.split("/")[2]) {
                    const id = window.location.pathname.split("/")[2]
                    const marker = leafletRefs[id]?.marker;
                    if (marker && marker != null) {
                        marker !== null && clusterRef?.current?.zoomToShowLayer(marker, () => {
                            marker.openPopup();
                        });
                        const item = leafletRefs[id]?.item;
                        let title = "";
                        if (item.name) title = item.name;
                        else if (item.layer?.itemNameField) title = getValue(item, item.layer.itemNameField);
                        document.title = `${document.title.split("-")[0]} - ${title}`;
                        document.querySelector('meta[property="og:title"]')?.setAttribute("content", item.name);
                        document.querySelector('meta[property="og:description"]')?.setAttribute("content", item.text);
                    }
                }
            }
        }

    }

    useEffect(() => {
        openPopup();
    }, [leafletRefs, location])

    useEffect(() => {
    }, [allTagsLoaded])
    
    useEffect(() => {
        if(tagsReady){
            newTagsToAdd.map(newtag => {
                addTag(newtag);
                setNewTagsToAdd(current =>
                    current.filter(tag => {
                        return tag.id !== newtag.id;
                      }),
                )
            })
        }
    }, [tagsReady])

    return (
        <>
            {items &&
                items.
                    filter(item => item.layer?.name === name)?.
                    filter(item =>
                        filterTags.length == 0 ? item : filterTags.every(tag => getItemTags(item).some(filterTag => filterTag.id.toLocaleLowerCase() === tag.id.toLocaleLowerCase())))?.
                    filter(item => item.layer && isLayerVisible(item.layer)).
                    map((item: Item) => {                      
                        if (getValue(item, itemLongitudeField) && getValue(item, itemLatitudeField)) {
                            item[itemTextField] = getValue(item, itemTextField);
                            if (item?.tags) {
                                item[itemTextField] = item[itemTextField] + '\n\n';
                                item.tags.map(tag => {
                                    if(!item[itemTextField].includes(`#${tag}`))
                                    return (item[itemTextField] = item[itemTextField] + `#${tag} `)
                                    return item[itemTextField]
    
                                });
                            }
                            if(allTagsLoaded) {
                                item[itemTextField].toLocaleLowerCase().match(hashTagRegex)?.map(tag=> {                                        
                                    if ((!tags.find((t) => t.id.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase()))&& !newTagsToAdd.find((t) => t.id.toLocaleLowerCase() === tag.slice(1).toLocaleLowerCase())) {
                                        const newTag = {id: tag.slice(1).toLocaleLowerCase(), color: randomColor()};
                                      setNewTagsToAdd(current => [...current, newTag]);
                                    }
                                });
                                !tagsReady && setTagsReady(true);
                            }  


                            const itemTtags = getItemTags(item);
                            
                            const latitude = itemLatitudeField && item ? getValue(item, itemLatitudeField) : undefined;
                            const longitude = itemLongitudeField && item ? getValue(item, itemLongitudeField) : undefined;

                            let color1 = markerDefaultColor;
                            let color2 = "RGBA(35, 31, 32, 0.2)";
                            if (itemColorField) color1 = getValue(item, itemColorField);

                            else if (itemTtags && itemTtags[0]) {
                                color1 = itemTtags[0].color;
                            }
                            if (itemTtags && itemTtags[0] && itemColorField) color2 = itemTtags[0].color;
                            else if (itemTtags && itemTtags[1]) {
                                color2 = itemTtags[1].color;
                            }
                            return (
                                <Marker ref={(r) => {
                                    if (!(item.id in leafletRefs && leafletRefs[item.id].marker == r))
                                        r && addMarker(item, r);
                                }} icon={MarkerIconFactory(markerShape, color1, color2, markerIcon)} key={item.id} position={[latitude, longitude]}>
                                    {
                                        (children && React.Children.toArray(children).some(child => React.isValidElement(child) && child.props.__TYPE === "ItemView") ?
                                            React.Children.toArray(children).map((child) =>
                                                React.isValidElement(child) && child.props.__TYPE === "ItemView" ?
                                                    <ItemViewPopup ref={(r) => {
                                                        if (!(item.id in leafletRefs && leafletRefs[item.id].popup == r))
                                                            r && addPopup(item, r as Popup);
                                                    }} key={item.id + item.name}
                                                        item={item}
                                                        setItemFormPopup={setItemFormPopup}>
                                                        {child}
                                                    </ItemViewPopup>
                                                    : ""
                                            )
                                            :
                                            <>
                                                <ItemViewPopup key={item.id + item.name} ref={(r) => {
                                                    if (!(item.id in leafletRefs && leafletRefs[item.id].popup == r))
                                                        r && addPopup(item, r as Popup);
                                                }}
                                                    item={item}
                                                    setItemFormPopup={setItemFormPopup} />
                                            </>)
                                    }
                                    <Tooltip offset={[0, -38]} direction='top'>{item.name ? item.name : getValue(item, itemNameField)}</Tooltip>
                                </Marker>
                            );
                        }
                        else return null;
                    })
            }
            {//{children}}
            }
            {itemFormPopup && itemFormPopup.layer!.name == name &&
                (children && React.Children.toArray(children).some(child => React.isValidElement(child) && child.props.__TYPE === "ItemForm") ?
                    React.Children.toArray(children).map((child) =>
                        React.isValidElement(child) && child.props.__TYPE === "ItemForm" ?
                            <ItemFormPopup key={setItemFormPopup?.name} position={itemFormPopup!.position} layer={itemFormPopup!.layer} setItemFormPopup={setItemFormPopup} item={itemFormPopup!.item} >{child}</ItemFormPopup>
                            : ""
                    )
                    :
                    <>
                        <ItemFormPopup position={itemFormPopup!.position} layer={itemFormPopup!.layer} setItemFormPopup={setItemFormPopup} item={itemFormPopup!.item} />
                    </>)
            }
        </>
    )
}