import { useCallback, useEffect, useRef, useState } from 'react'
import 'ol/ol.css'
import Map from 'ol/Map'
import View from 'ol/View'
import { Draw, Modify, Select, Snap, Translate } from 'ol/interaction'
import { ImageStatic, OSM, Vector as VectorSource, XYZ } from 'ol/source'
import { Tile as TileLayer, VectorImage, Vector as VectorLayer } from 'ol/layer'
import { click, never, platformModifierKeyOnly, primaryAction, shiftKeyOnly } from 'ol/events/condition'
import Feature from 'ol/Feature'
import { IRectCoords, SatelliteMapsProvider } from '../../interfaces/map'
import { Extent } from 'ol/extent'
import { drawingLayerStyle, highlightStyleRed, highlightStyleYellow, overlayStyle, regionsLayerStyle } from './MapStyles'
import { googleMapsSatelliteSource, regionsLayerSource, yandexMapsSatelliteSource } from './MapSources'
import ImageLayer from 'ol/layer/Image'
import { LineString, Point, SimpleGeometry } from 'ol/geom'
import { fromExtent } from 'ol/geom/Polygon'
import Collection from 'ol/Collection'
import { Coordinate } from 'ol/coordinate'
import { addInteractions, calculateCenter, loadFeatures, processFigure, processLine, regionsInit, saveFeatures, updateImageSource } from './mapUtils'
import MapBrowserEvent from 'ol/MapBrowserEvent'
import { get, transform } from 'ol/proj'
import useSWR from 'swr'
import { fetcher } from '../../http/axiosInstance'
import { BASE_URL } from '../../constants'
import { Accordion, ActionIcon, Autocomplete, Box, CloseButton, Flex, Select as MantineSelect, MantineStyleProp, rem, ScrollAreaAutosize, Slider, useMantineColorScheme, Portal, Timeline, Text, Stack, NavLink, Grid, Checkbox } from '@mantine/core'
import { IconPlus, IconSearch, IconSettings, IconTable, IconUpload } from '@tabler/icons-react'
import { getGridCellPosition } from './mapUtils'
import { IFigure, ILine } from '../../interfaces/gis'
import axios from 'axios'
import ObjectParameter from './ObjectParameter'
import { IObjectParam } from '../../interfaces/objects'
import MapToolbar from './MapToolbar/MapToolbar'
import MapStatusbar from './MapStatusbar/MapStatusbar'
import { measureStyleFunction, modifyStyle } from './Measure/MeasureStyles'
import { useMapStore } from '../../store/map'
import { v4 as uuidv4 } from 'uuid'
import { useThrottle } from '@uidotdev/usehooks'
import ObjectTree from '../Tree/ObjectTree'
import { setCurrentObjectId, setSelectedCity, setSelectedYear, useObjectsStore } from '../../store/objects'

// Settings for cities
const citySettings = [
    {
        city_id: 145,
        // scale: 10000,
        scale: 9000,
        offset_x: 14442665.697619518,
        offset_y: 8884520.63524492,
        rotation: 0
    }
]

const MapComponent = () => {
    const { selectedCity, selectedYear, currentObjectId } = useObjectsStore()

    const mapState = useMapStore()

    const [currentCoordinate, setCurrentCoordinate] = useState<Coordinate | null>(null)
    const [currentZ, setCurrentZ] = useState<number | undefined>(undefined)
    const [currentX, setCurrentX] = useState<number | undefined>(undefined)
    const [currentY, setCurrentY] = useState<number | undefined>(undefined)

    const [file, setFile] = useState<File | null>(null)
    const [polygonExtent, setPolygonExtent] = useState<Extent | undefined>(undefined)

    const [rectCoords, setRectCoords] = useState<IRectCoords | undefined>(undefined)

    // Measure
    const measureSource = useRef(new VectorSource())
    const measureModify = useRef(new Modify({ source: measureSource.current, style: modifyStyle }))

    const measureLayer = useRef(new VectorLayer({
        source: measureSource.current,
        style: function (feature) {
            return measureStyleFunction(feature);
        },
        properties: {
            id: uuidv4(),
            type: 'measure',
            name: 'Линейка'
        }
    }))

    const measureDraw = useRef<Draw | null>(null)

    /////

    const mapElement = useRef<HTMLDivElement | null>(null)

    const map = useRef<Map | null>(null)

    const [satMapsProvider, setSatMapsProvider] = useState<SatelliteMapsProvider>('custom')

    const gMapsSatSource = useRef<XYZ>(googleMapsSatelliteSource)

    const customMapSource = useRef<XYZ>(new XYZ({
        url: `${import.meta.env.VITE_API_EMS_URL}/tiles/tile/custom/{z}/{x}/{y}`,
        attributions: 'Custom map data'
    }))

    const yMapsSatSource = useRef<XYZ>(yandexMapsSatelliteSource)

    const satLayer = useRef<TileLayer>(new TileLayer({
        source: gMapsSatSource.current,
        properties: {
            id: uuidv4(),
            name: 'Спутник'
        }
    }))

    const draw = useRef<Draw | null>(null)
    const snap = useRef<Snap | null>(null)

    const selectFeature = useRef<Select>(new Select({
        condition: function (mapBrowserEvent) {
            return click(mapBrowserEvent) && shiftKeyOnly(mapBrowserEvent);
        },
    }))

    const nodeLayer = useRef<VectorLayer | null>(null)
    const nodeLayerSource = useRef<VectorSource>(new VectorSource())

    const overlayLayer = useRef<VectorLayer | null>(null)
    const overlayLayerSource = useRef<VectorSource>(new VectorSource())

    const drawingLayer = useRef<VectorLayer | null>(null)
    const drawingLayerSource = useRef<VectorSource>(new VectorSource())

    const citiesLayer = useRef<VectorLayer>(new VectorLayer({
        source: new VectorSource(),
        properties: {
            id: uuidv4(),
            name: 'Города'
        }
    }))

    const figuresLayer = useRef<VectorImage>(new VectorImage({
        source: new VectorSource(),
        declutter: true,
        properties: {
            id: uuidv4(),
            name: 'Фигуры'
        }
    }))

    const linesLayer = useRef<VectorImage>(new VectorImage({
        source: new VectorSource(),
        declutter: true,
        properties: {
            id: uuidv4(),
            name: 'Линии'
        }
    }))

    const regionsLayer = useRef<VectorImage>(new VectorImage({
        source: regionsLayerSource,
        declutter: true,
        style: regionsLayerStyle,
        properties: {
            id: uuidv4(),
            name: 'Регион'
        }
    }))

    const selectedRegion = useRef<Feature | null>(null)

    const baseLayer = useRef<TileLayer>(new TileLayer({
        source: new OSM(),
        properties: {
            id: uuidv4(),
            name: 'OpenStreetMap'
        }
    }))

    const imageLayer = useRef<ImageLayer<ImageStatic>>(new ImageLayer({
        properties: {
            id: uuidv4(),
            name: 'Изображение'
        }
    }))

    // tile processing
    const handleImageDrop = useCallback((event: DragEvent) => {
        event.preventDefault();
        event.stopPropagation();

        if (!event.dataTransfer?.files) return

        const files = event.dataTransfer.files;
        if (files.length > 0) {
            const file = files[0];
            setFile(file)

            if (file.type.startsWith('image/')) {
                const reader = new FileReader();

                reader.onload = () => {
                    const imageUrl = reader.result as string;
                    const img = new Image();
                    img.src = imageUrl;
                    img.onload = () => {
                        if (map.current) {
                            const view = map.current.getView();
                            const center = view.getCenter() || [0, 0];

                            const width = img.naturalWidth;
                            const height = img.naturalHeight;
                            const resolution = view.getResolution() || 0;

                            const extent = [
                                center[0] - (width * resolution) / 20,
                                center[1] - (height * resolution) / 20,
                                center[0] + (width * resolution) / 20,
                                center[1] + (height * resolution) / 20,
                            ];

                            // Create a polygon feature with the same extent as the image
                            const polygonFeature = new Feature({
                                geometry: fromExtent(extent),
                            });

                            // Add the polygon feature to the drawing layer source
                            overlayLayerSource.current?.addFeature(polygonFeature);

                            // Set up the initial image layer with the extent
                            const imageSource = new ImageStatic({
                                url: imageUrl,
                                imageExtent: extent,
                            });
                            imageLayer.current.setSource(imageSource);

                            //map.current.addLayer(imageLayer.current);

                            // Add interactions for translation and scaling
                            const translate = new Translate({
                                layers: [imageLayer.current],
                                features: new Collection([polygonFeature]),
                            });

                            const defaultStyle = new Modify({ source: overlayLayerSource.current })
                                .getOverlay()
                                .getStyleFunction();

                            const modify = new Modify({
                                insertVertexCondition: never,
                                source: overlayLayerSource.current,
                                condition: function (event) {
                                    return primaryAction(event) && !platformModifierKeyOnly(event);
                                },
                                deleteCondition: never,
                                features: new Collection([polygonFeature]),
                                style: function (feature) {
                                    feature.get('features').forEach(function (modifyFeature: Feature) {
                                        const modifyGeometry = modifyFeature.get('modifyGeometry')
                                        if (modifyGeometry) {
                                            const point = (feature.getGeometry() as Point).getCoordinates()
                                            let modifyPoint = modifyGeometry.point
                                            if (!modifyPoint) {
                                                // save the initial geometry and vertex position
                                                modifyPoint = point;
                                                modifyGeometry.point = modifyPoint;
                                                modifyGeometry.geometry0 = modifyGeometry.geometry;
                                                // get anchor and minimum radius of vertices to be used
                                                const result = calculateCenter(modifyGeometry.geometry0);
                                                modifyGeometry.center = result.center;
                                                modifyGeometry.minRadius = result.minRadius;
                                            }
                                            const center = modifyGeometry.center;
                                            const minRadius = modifyGeometry.minRadius;
                                            let dx, dy;
                                            dx = modifyPoint[0] - center[0];
                                            dy = modifyPoint[1] - center[1];
                                            const initialRadius = Math.sqrt(dx * dx + dy * dy);
                                            if (initialRadius > minRadius) {
                                                const initialAngle = Math.atan2(dy, dx);
                                                dx = point[0] - center[0];
                                                dy = point[1] - center[1];
                                                const currentRadius = Math.sqrt(dx * dx + dy * dy);
                                                if (currentRadius > 0) {
                                                    const currentAngle = Math.atan2(dy, dx);
                                                    const geometry = modifyGeometry.geometry0.clone();
                                                    geometry.scale(currentRadius / initialRadius, undefined, center);
                                                    geometry.rotate(currentAngle - initialAngle, center);
                                                    modifyGeometry.geometry = geometry;
                                                }
                                            }
                                        }
                                    })
                                    const res = map?.current?.getView()?.getResolution()
                                    if (typeof res === 'number' && feature && defaultStyle) {
                                        return defaultStyle(feature, res)
                                    }
                                }
                            });

                            translate.on('translateend', () => updateImageSource(imageUrl, imageLayer, polygonFeature, setPolygonExtent, setRectCoords));
                            //modify.on('modifyend', updateImageSource);

                            modify.on('modifystart', function (event) {
                                event.features.forEach(function (feature) {
                                    feature.set(
                                        'modifyGeometry',
                                        { geometry: feature.getGeometry()?.clone() },
                                        true,
                                    );
                                });
                            });

                            modify.on('modifyend', function (event) {
                                event.features.forEach(function (feature) {
                                    const modifyGeometry = feature.get('modifyGeometry');
                                    if (modifyGeometry) {
                                        feature.setGeometry(modifyGeometry.geometry);
                                        feature.unset('modifyGeometry', true);
                                    }
                                })
                                updateImageSource(imageUrl, imageLayer, polygonFeature, setPolygonExtent, setRectCoords)
                            })

                            map.current.addInteraction(translate);
                            map.current.addInteraction(modify);
                        }
                    };
                };
                reader.readAsDataURL(file);
            }
        }
    }, [])

    useEffect(() => {
        drawingLayer.current = new VectorLayer({
            source: drawingLayerSource.current,
            style: drawingLayerStyle,
            properties: {
                id: uuidv4(),
                name: 'Чертеж'
            }
        })

        overlayLayer.current = new VectorLayer({
            source: overlayLayerSource.current,
            style: overlayStyle,
            properties: {
                id: uuidv4(),
                name: 'Наложения'
            }
        })

        nodeLayer.current = new VectorLayer({
            source: nodeLayerSource.current,
            style: drawingLayerStyle,
            properties: {
                id: uuidv4(),
                name: 'Узлы'
            }
        })

        map.current = new Map({
            controls: [],
            layers: [
                baseLayer.current,
                satLayer.current,
                regionsLayer.current,
                citiesLayer.current,
                linesLayer.current,
                figuresLayer.current,
                drawingLayer.current,
                imageLayer.current,
                overlayLayer.current,
                nodeLayer.current,
                measureLayer.current
            ],
            target: mapElement.current as HTMLDivElement,
            view: new View({
                center: transform([129.7466541, 62.083504], 'EPSG:4326', 'EPSG:3857'),//center: fromLonLat([130.401113, 67.797368]),
                zoom: 16,
                maxZoom: 21,
                //extent: mapExtent,
            }),
        })

        map.current.on('pointermove', function (e: MapBrowserEvent<UIEvent>) {
            setCurrentCoordinate(e.coordinate)
            const currentExtent = get('EPSG:3857')?.getExtent() as Extent
            const { tileX, tileY } = getGridCellPosition(e.coordinate[0], e.coordinate[1], currentExtent, Number(map.current?.getView().getZoom()?.toFixed(0)))
            setCurrentZ(Number(map.current?.getView().getZoom()?.toFixed(0)))
            setCurrentX(tileX)
            setCurrentY(tileY)
        })

        map.current.on('click', function (e: MapBrowserEvent<UIEvent>) {
            const pixel = map.current?.getEventPixel(e.originalEvent)

            if (pixel) {
                map.current?.forEachFeatureAtPixel(pixel, function (feature) {
                    setCurrentObjectId(feature.get('object_id'))
                })
            }
        })

        const modify = new Modify({ source: drawingLayerSource.current })
        map.current.addInteraction(modify)

        map.current.addInteraction(selectFeature.current)

        selectFeature.current.on('select', (e) => {
            const selectedFeatures = e.selected

            if (selectedFeatures.length > 0) {
                selectedFeatures.forEach((feature) => {
                    drawingLayerSource.current?.removeFeature(feature)
                })
            }
        })

        loadFeatures(drawingLayerSource)

        regionsInit(map, selectedRegion, regionsLayer, setStatusText)

        if (mapElement.current) {
            mapElement.current.addEventListener('dragover', (e) => {
                e.preventDefault()
            })

            mapElement.current.addEventListener('drop', handleImageDrop)
        }

        return () => {
            map?.current?.setTarget(undefined)

            if (mapElement.current) {
                mapElement.current.removeEventListener('drop', handleImageDrop)
            }
        }
    }, [])

    useEffect(() => {
        if (mapState.currentTool) {
            if (draw.current) map?.current?.removeInteraction(draw.current)
            //if (snap.current) map?.current?.removeInteraction(snap.current)
            addInteractions(drawingLayerSource, draw, map, snap, measureDraw, measureSource, measureModify)
        } else {
            if (draw.current) map?.current?.removeInteraction(draw.current)
            if (snap.current) map?.current?.removeInteraction(snap.current)
            if (measureDraw.current) map?.current?.removeInteraction(measureDraw.current)
        }
    }, [mapState.currentTool])

    const [satelliteOpacity, setSatelliteOpacity] = useState<number>(0)

    const [statusText, setStatusText] = useState('')

    // Visibility setting
    useEffect(() => {
        satLayer.current?.setOpacity(satelliteOpacity)

        if (satelliteOpacity == 0) {
            baseLayer.current?.setVisible(true)
            satLayer.current?.setVisible(false)
        } if (satelliteOpacity == 1) {
            baseLayer.current?.setVisible(false)
            satLayer.current?.setVisible(true)
        } else if (satelliteOpacity > 0 && satelliteOpacity < 1) {
            baseLayer.current?.setVisible(true)
            satLayer.current?.setVisible(true)
        }
    }, [satelliteOpacity])

    // Satellite tiles setting
    useEffect(() => {
        satLayer.current?.setSource(satMapsProvider == 'google' ? gMapsSatSource.current : satMapsProvider == 'yandex' ? yMapsSatSource.current : satMapsProvider == 'custom' ? customMapSource.current : gMapsSatSource.current)
        satLayer.current?.getSource()?.refresh()
    }, [satMapsProvider])

    const submitOverlay = async () => {
        if (file && polygonExtent && rectCoords?.bl && rectCoords?.tl && rectCoords?.tr && rectCoords?.br) {
            const formData = new FormData()
            formData.append('file', file)
            formData.append('extentMinX', polygonExtent[0].toString())
            formData.append('extentMinY', polygonExtent[1].toString())
            formData.append('extentMaxX', polygonExtent[2].toString())
            formData.append('extentMaxY', polygonExtent[3].toString())
            formData.append('blX', rectCoords?.bl[0].toString())
            formData.append('blY', rectCoords?.bl[1].toString())
            formData.append('tlX', rectCoords?.tl[0].toString())
            formData.append('tlY', rectCoords?.tl[1].toString())
            formData.append('trX', rectCoords?.tr[0].toString())
            formData.append('trY', rectCoords?.tr[1].toString())
            formData.append('brX', rectCoords?.br[0].toString())
            formData.append('brY', rectCoords?.br[1].toString())

            await fetch(`${import.meta.env.VITE_API_EMS_URL}/tiles/upload`, { method: 'POST', body: formData })
        }
    }

    const { colorScheme } = useMantineColorScheme();

    const mapControlsStyle: MantineStyleProp = {
        borderRadius: '4px',
        position: 'absolute',
        zIndex: '1',
        // backgroundColor: (theme) =>
        //     theme.palette.mode === 'light'
        //         ? '#FFFFFFAA'
        //         : '#000000AA',
        backgroundColor: colorScheme === 'light' ? '#FFFFFFAA' : '#000000AA',
        backdropFilter: 'blur(8px)',
        border: '1px solid #00000022'
    }

    const { data: nodes } = useSWR('/nodes/all', () => fetcher('/nodes/all', BASE_URL.ems), { revalidateOnFocus: false })

    useEffect(() => {
        // Draw features based on database data
        if (Array.isArray(nodes)) {
            nodes.map(node => {
                if (node.shape_type === 'LINE') {
                    const coordinates: Coordinate[] = []
                    if (Array.isArray(node.shape)) {
                        node.shape.map((point: any) => {
                            const coordinate = [point.x as number, point.y as number] as Coordinate
                            coordinates.push(coordinate)
                        })
                    }
                    //console.log(coordinates)
                    nodeLayerSource.current.addFeature(new Feature({ geometry: new LineString(coordinates) }))
                }
            })
        }
    }, [nodes])

    const [citiesPage, setCitiesPage] = useState<number>(0)

    const [searchCity, setSearchCity] = useState<string | undefined>("")
    const throttledSearchCity = useThrottle(searchCity, 500);

    const [searchObject, setSearchObject] = useState<string | undefined>("")
    const throttledSearchObject = useThrottle(searchObject, 500);

    const [selectedObjectList, setSelectedObjectList] = useState<number | null>(null)

    useEffect(() => {
        if (!selectedObjectList || !map.current) return;

        if (figuresLayer.current) {
            // Reset styles and apply highlight to matching features
            figuresLayer.current.getSource()?.getFeatures().forEach((feature) => {
                if (selectedObjectList == feature.get('type')) {
                    feature.setStyle(highlightStyleYellow);
                } else {
                    feature.setStyle(undefined); // Reset to default style
                }
            })
        }

        if (linesLayer.current) {
            // Reset styles and apply highlight to matching features
            linesLayer.current.getSource()?.getFeatures().forEach((feature) => {
                if (selectedObjectList == feature.get('type')) {
                    feature.setStyle(highlightStyleYellow);
                } else {
                    feature.setStyle(undefined); // Reset to default style
                }
            })
        }
    }, [selectedObjectList])

    useEffect(() => {
        if (currentObjectId) {
            if (figuresLayer.current) {
                // Reset styles and apply highlight to matching features
                figuresLayer.current.getSource()?.getFeatures().forEach((feature: Feature) => {
                    if (currentObjectId == feature.get('object_id')) {
                        feature.setStyle(highlightStyleRed);

                        const geometry = feature.getGeometry()

                        if (geometry) {
                            map.current?.getView().fit(geometry as SimpleGeometry, { duration: 500, maxZoom: 18 })
                            //map.current?.getView().animate({ center: calculateCenter(geometry as SimpleGeometry).center })
                        }

                    } else {
                        feature.setStyle(undefined); // Reset to default style
                    }
                })
            }

            if (linesLayer.current) {
                // Reset styles and apply highlight to matching features
                linesLayer.current.getSource()?.getFeatures().forEach((feature: Feature) => {
                    if (currentObjectId == feature.get('object_id')) {
                        feature.setStyle(highlightStyleRed);

                        const geometry = feature.getGeometry()
                        if (geometry) {
                            map.current?.getView().fit(geometry as SimpleGeometry, { duration: 500, maxZoom: 18 })
                        }
                    } else {
                        feature.setStyle(undefined); // Reset to default style
                    }
                })
            }
        }
    }, [currentObjectId])

    const { data: valuesData } = useSWR(
        currentObjectId ? `/general/values/all?object_id=${currentObjectId}` : null,
        (url) => fetcher(url, BASE_URL.ems),
        {
            revalidateOnFocus: false,
            revalidateIfStale: false
        }
    )

    const { data: citiesData } = useSWR(
        `/general/cities/all?limit=${10}&offset=${citiesPage || 0}${throttledSearchCity ? `&search=${throttledSearchCity}` : ''}`,
        (url) => fetcher(url, BASE_URL.ems),
        {
            revalidateOnFocus: false
        }
    )

    const { data: searchData } = useSWR(
        throttledSearchObject !== "" && selectedCity && selectedYear ? `/general/search/objects?q=${throttledSearchObject}&id_city=${selectedCity}&year=${selectedYear}` : null,
        (url) => fetcher(url, BASE_URL.ems),
        {
            revalidateOnFocus: false
        }
    )

    const { data: figuresData, isValidating: figuresValidating } = useSWR(
        selectedCity && selectedYear ? `/gis/figures/all?city_id=${selectedCity}&year=${selectedYear}&offset=0&limit=${10000}` : null,
        (url) => axios.get(url, {
            baseURL: BASE_URL.ems
        }).then((res) => res.data),
        {
            revalidateOnFocus: false
        }
    )

    const { data: linesData } = useSWR(
        !figuresValidating && selectedCity && selectedYear ? `/gis/lines/all?city_id=${selectedCity}&year=${selectedYear}&offset=0&limit=${10000}` : null,
        (url) => axios.get(url, {
            baseURL: BASE_URL.ems
        }).then((res) => {
            return res.data
        }),
        {
            revalidateOnFocus: false
        }
    )

    useEffect(() => {
        let offset_x = 14444582.697619518
        let offset_y = 8866450.63524492
        let scale = {
            w: 100000,
            h: 100000
        }
        let rotation = 0

        if (citySettings.find(el => el.city_id === selectedCity)) {
            console.log("City settings found")

            if (citySettings.find(el => el.city_id === selectedCity)?.scale) {
                scale = {
                    w: citySettings.find(el => el.city_id === selectedCity).scale,
                    h: citySettings.find(el => el.city_id === selectedCity).scale
                }
            }
            if (citySettings.find(el => el.city_id === selectedCity)?.offset_x && citySettings.find(el => el.city_id === selectedCity)?.offset_y) {
                offset_x = citySettings.find(el => el.city_id === selectedCity).offset_x
                offset_y = citySettings.find(el => el.city_id === selectedCity).offset_y
            }

            if (citySettings.find(el => el.city_id === selectedCity)?.rotation) {
                rotation = citySettings.find(el => el.city_id === selectedCity)?.rotation
            }
        } else {
            console.log("City settings NOT found")
        }

        if (Array.isArray(figuresData)) {
            figuresLayer.current.getSource()?.clear()
            if (figuresData.length > 0) {
                const scaling = {
                    w: scale.w, // responseData[0].width
                    h: scale.h // responseData[0].width
                }

                figuresData.map((figure: IFigure) => {
                    processFigure(figure, scaling, [offset_x, offset_y], figuresLayer)
                })
            }
        }

        if (Array.isArray(linesData)) {
            linesLayer.current.getSource()?.clear()
            if (linesData.length > 0) {
                const scaling = {
                    w: scale.w, // responseData[0].width
                    h: scale.h // responseData[0].width
                }

                linesData.map((line: ILine) => {
                    processLine(line, scaling, [offset_x, offset_y], linesLayer)
                })
            }
        }
    }, [figuresData, linesData, selectedCity, selectedYear])


    useEffect(() => {
        // if (map.current) {
        //     map.current.on('postcompose', function () {
        //         if (colorScheme === 'dark') {
        //             document.querySelector('canvas').style.filter = 'grayscale(80%) invert(100%) hue-rotate(180deg)'
        //         } else {
        //             document.querySelector('canvas').style.filter = 'grayscale(0%) invert(0%) hue-rotate(0deg)'
        //         }
        //     })
        // }

        if (baseLayer.current) {
            baseLayer.current.on('prerender', function (e) {
                if (colorScheme === 'dark') {
                    if (e.context) {
                        const context = e.context as CanvasRenderingContext2D;
                        context.filter = 'grayscale(80%) invert(100%) hue-rotate(180deg) ';
                        context.globalCompositeOperation = 'source-over';
                    }
                } else {
                    if (e.context) {
                        const context = e.context as CanvasRenderingContext2D;
                        context.filter = 'none';
                    }
                }
            })

            baseLayer.current.on('postrender', function (e) {
                if (e.context) {
                    const context = e.context as CanvasRenderingContext2D;
                    context.filter = 'none';
                }
            })
        }
    }, [colorScheme])

    return (
        <Box w={'100%'} h='100%' pos={'relative'}>
            <Portal target='#header-portal'>
                <Flex gap={'sm'} direction={'row'}>
                    <Flex align='center' direction='row' gap='sm'>
                        <Slider w='100%' min={0} max={1} step={0.001} value={satelliteOpacity} defaultValue={satelliteOpacity} onChange={(value) => setSatelliteOpacity(Array.isArray(value) ? value[0] : value)} />

                        <MantineSelect variant='filled' value={satMapsProvider} data={[{ label: 'Google', value: 'google' }, { label: 'Yandex', value: 'yandex' }, { label: 'Custom', value: 'custom' }]} onChange={(value) => setSatMapsProvider(value as SatelliteMapsProvider)} />
                    </Flex>

                    <form>
                        <Autocomplete
                            placeholder="Поиск"
                            flex={'1'}
                            data={searchData ? searchData.map((item: { value: string, id_object: string }) => ({ label: item.value, value: item.id_object.toString() })) : []}
                            //onSelect={(e) => console.log(e.currentTarget.value)}
                            onChange={(value) => setSearchObject(value)}
                            onOptionSubmit={(value) => setCurrentObjectId(value)}
                            rightSection={
                                searchObject !== '' && (
                                    <CloseButton
                                        size="sm"
                                        onMouseDown={(event) => event.preventDefault()}
                                        onClick={() => {
                                            setSearchObject('')
                                            //setSelectedCity(null)
                                        }}
                                        aria-label="Clear value"
                                    />
                                )
                            }
                            leftSection={<IconSearch size={16} />}
                            value={searchObject}
                        />
                    </form>

                    <form>
                        <Autocomplete
                            placeholder="Район"
                            flex={'1'}
                            data={citiesData ? citiesData.map((item: { name: string, id: number }) => ({ label: item.name, value: item.id.toString() })) : []}
                            //onSelect={(e) => console.log(e.currentTarget.value)}
                            onChange={(value) => setSearchCity(value)}
                            onOptionSubmit={(value) => setSelectedCity(Number(value))}
                            rightSection={
                                searchCity !== '' && (
                                    <CloseButton
                                        size="sm"
                                        onMouseDown={(event) => event.preventDefault()}
                                        onClick={() => {
                                            setSearchCity('')
                                            setSelectedCity(null)
                                        }}
                                        aria-label="Clear value"
                                    />
                                )
                            }
                            value={searchCity}
                        />
                    </form>

                    <MantineSelect
                        w='84px'
                        data={['2018', '2019', '2020', '2021', '2022', '2023', '2024'].map(el => ({ label: el, value: el }))}
                        onChange={(e) => {
                            setSelectedYear(Number(e))
                        }}
                        defaultValue={selectedYear?.toString()}
                        allowDeselect={false}
                    />

                    <ActionIcon
                        size='lg'
                        variant='transparent'
                        title='Настройки ИКС'
                    >
                        <IconSettings style={{ width: rem(20), height: rem(20) }} />
                    </ActionIcon>
                </Flex>
            </Portal>

            <Flex w={'100%'} h={'100%'} pos={'absolute'}>
                <MapToolbar
                    onSave={() => saveFeatures(drawingLayer)}
                    onRemove={() => draw.current?.removeLastPoint()}
                    onMover={() => map?.current?.addInteraction(new Translate())}
                    colorScheme={colorScheme}
                />

                <Flex direction='column' mah={'86%'} pl='sm' style={{
                    ...mapControlsStyle,
                    maxWidth: '340px',
                    width: '100%',
                    top: '8px',
                    left: '8px',
                }}>
                    <ScrollAreaAutosize offsetScrollbars>
                        <Stack>
                            <Flex direction='row'>
                                <ActionIcon
                                    size='lg'
                                    variant='transparent'
                                    onClick={() => submitOverlay()}
                                >
                                    <IconUpload style={{ width: rem(20), height: rem(20) }} />
                                </ActionIcon>

                                <ActionIcon
                                    size='lg'
                                    variant='transparent'
                                    title='Добавить подложку'
                                >
                                    <IconPlus style={{ width: rem(20), height: rem(20) }} />
                                </ActionIcon>
                            </Flex>

                            {selectedCity &&
                                <Accordion variant='filled' style={{ backgroundColor: 'transparent' }} defaultValue='Объекты'>
                                    <Accordion.Item key={'objects'} value={'Объекты'}>
                                        <Accordion.Control icon={<IconTable />}>{'Объекты'}</Accordion.Control>
                                        <Accordion.Panel>
                                            <ObjectTree />
                                        </Accordion.Panel>
                                    </Accordion.Item>

                                    {valuesData &&
                                        <Accordion.Item key={'parameters'} value={'Параметры объекта'}>
                                            <Accordion.Control icon={<IconTable />}>{'Параметры объекта'}</Accordion.Control>
                                            <Accordion.Panel>
                                                <Flex gap={'sm'} direction={'column'}>
                                                    {Array.isArray(valuesData) &&
                                                        Object.entries(
                                                            valuesData.reduce((acc, param) => {
                                                                if (!acc[param.id_param]) {
                                                                    acc[param.id_param] = [];
                                                                }
                                                                acc[param.id_param].push(param);
                                                                return acc;
                                                            }, {} as Record<string, IObjectParam[]>)
                                                        ).map(([id_param, params]) => {
                                                            // Step 1: Sort the parameters by date_s (start date) and date_po (end date)
                                                            const sortedParams = (params as IObjectParam[]).sort((b, a) => {
                                                                const dateA = new Date(a.date_s || 0);
                                                                const dateB = new Date(b.date_s || 0);
                                                                return dateA.getTime() - dateB.getTime();
                                                            });

                                                            return sortedParams.length > 1 ? (
                                                                // Step 2: Render Mantine Timeline for multiple entries with the same `id_param`
                                                                <Timeline
                                                                    key={id_param}
                                                                    active={0}
                                                                    bulletSize={18}
                                                                >
                                                                    {sortedParams.map((param: IObjectParam, index: number) => (
                                                                        <Timeline.Item
                                                                            key={index}
                                                                            style={{
                                                                                filter: index !== 0 ? 'grayscale(100%) opacity(50%)' : 'none'
                                                                            }}
                                                                        >
                                                                            <ObjectParameter param={param} showLabel={false} />
                                                                            <Text size='xs'>
                                                                                {new Date(param.date_s).toLocaleDateString('en-GB').split('/').join('.')} - {new Date(param.date_po).toLocaleDateString('en-GB') === '01/01/1970' ? 'По сей день' : new Date(param.date_po).toLocaleDateString('en-GB').split('/').join('.')}
                                                                            </Text>
                                                                        </Timeline.Item>
                                                                    ))}
                                                                </Timeline>
                                                            ) : (
                                                                <ObjectParameter key={id_param} param={sortedParams[0]} />
                                                            );
                                                        })
                                                    }
                                                </Flex>
                                            </Accordion.Panel>
                                        </Accordion.Item>
                                    }
                                </Accordion>
                            }

                            <Accordion variant='filled' style={{ backgroundColor: 'transparent' }} defaultValue='Слои'>
                                <Accordion.Item key={'objects'} value={'Слои'}>
                                    <Accordion.Control icon={<IconTable />}>{'Слои'}</Accordion.Control>
                                    <Accordion.Panel>
                                        {map.current?.getLayers().getArray() && map.current?.getLayers().getArray().map((layer, index) => (
                                            <Flex key={`layer-${index}`} gap='xs' align='center'>
                                                <Checkbox.Indicator
                                                    checked={layer.getLayerState().visible}
                                                    onClick={() => layer.getLayerState().visible ? layer.setVisible(false) : layer.setVisible(true)}
                                                />
                                                <NavLink p={0} label={layer.get('name')} onClick={() => { console.log(layer.getLayerState()) }} />
                                            </Flex>
                                        ))}
                                    </Accordion.Panel>
                                </Accordion.Item>
                            </Accordion>
                        </Stack>
                    </ScrollAreaAutosize>
                </Flex>

                <MapStatusbar
                    mapControlsStyle={mapControlsStyle}
                    currentCoordinate={currentCoordinate}
                    currentX={currentX}
                    currentY={currentY}
                    currentZ={currentZ}
                    statusText={statusText}
                />
            </Flex>

            <div
                id="map-container"
                ref={mapElement}
                style={{
                    width: '100%',
                    height: '100%',
                    maxHeight: '100%',
                    position: 'fixed',
                    flexGrow: 1
                }}
            >
            </div>
        </Box >
    );
};

export default MapComponent
