import React, {useState, useEffect} from 'react';
import {createRoot} from 'react-dom/client';
import {Map} from 'react-map-gl';
import maplibregl from 'maplibre-gl';
import {AmbientLight, PointLight, LightingEffect} from '@deck.gl/core';
import DeckGL from '@deck.gl/react';
import {PolygonLayer} from '@deck.gl/layers';
import {TripsLayer} from '@deck.gl/geo-layers';
import { Box } from '@mui/system';


// Source data CSV, Attribution to CARTO, OpenStreetMap contributors to deck.gl trips-layer example
const DATA_URL = {
  BUILDINGS:'https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/trips/buildings.json', // eslint-disable-line
  TRIPS: 'https://raw.githubusercontent.com/visgl/deck.gl-data/master/examples/trips/trips-v7.json' // eslint-disable-line
};

const ambientLight = new AmbientLight({
  color: [255, 255, 255],
  intensity: 1.0
});

const pointLight = new PointLight({
  color: [255, 255, 255],
  intensity: 2.0,
  position: [-74.05, 40.7, 8000]
});

const lightingEffect = new LightingEffect({ambientLight, pointLight});

const material = {
  ambient: 0.1,
  diffuse: 0.6,
  shininess: 32,
  specularColor: [60, 64, 70]
};

const DEFAULT_THEME = {
  buildingColor: [74, 80, 87],
  trailColor0: [253, 128, 93],
  trailColor1: [23, 184, 190],
  material,
  effects: [lightingEffect]
};

const INITIAL_VIEW_STATE = {
  longitude: -6.2760296,
  latitude: 53.362321,
  zoom: 13,
  pitch: 45,
  bearing: 0
};

const MAP_STYLE = 'https://basemaps.cartocdn.com/gl/dark-matter-nolabels-gl-style/style.json';

const landCover = [
  [
    [-74.0, 40.7],
    [-74.02, 40.7],
    [-74.02, 40.72],
    [-74.0, 40.72]
  ]
];

export default function Map3D({
    buildings = DATA_URL.BUILDINGS,
    trips = DATA_URL.TRIPS,
    trailLength = 180,
    initialViewState = INITIAL_VIEW_STATE,
    mapStyle = MAP_STYLE,
    theme = DEFAULT_THEME,
    loopLength = 1800,
    animationSpeed = 1
  }) {
    const [time, setTime] = useState(0);
    const [animation] = useState({});
  
    const animate = () => {
      setTime(t => (t + animationSpeed) % loopLength);
      animation.id = window.requestAnimationFrame(animate);
    };
  
    useEffect(() => {
      animation.id = window.requestAnimationFrame(animate);
      return () => window.cancelAnimationFrame(animation.id);
    }, [animation]);
  
    const layers = [
      new PolygonLayer({
        id: 'ground',
        data: landCover,
        getPolygon: f => f,
        stroked: false,
        getFillColor: [0, 0, 0, 0]
      }),
      new TripsLayer({
        id: 'trips',
        data: trips,
        getPath: d => d.path,
        getTimestamps: d => d.timestamps,
        getColor: d => (d.vendor === 0 ? theme.trailColor0 : theme.trailColor1),
        opacity: 0.3,
        widthMinPixels: 2,
        rounded: true,
        trailLength,
        currentTime: time,
  
        shadowEnabled: false
      }),
      new PolygonLayer({
        id: 'buildings',
        data: buildings,
        extruded: true,
        wireframe: false,
        opacity: 0.5,
        getPolygon: f => f.polygon,
        getElevation: f => f.height,
        getFillColor: theme.buildingColor,
        material: theme.material
      })
    ];
  
    return (
        <Box sx={{ width: '100%', height: '100%', position: 'relative', borderRadius: '15px', overflow: 'hidden'}}>
            <DeckGL
                style={{ width: '100%', height: '100%', position: 'absolute'}}
                layers={layers}
                effects={theme.effects}
                initialViewState={initialViewState}
                controller={true}
            >
                <Map reuseMaps mapLib={maplibregl} mapStyle={mapStyle} preventStyleDiffing={true} attributionControl={false} />
            </DeckGL>
        </Box>
    );
  }
  