import { default as L, default as Leaflet } from 'leaflet';
import 'leaflet-svg-shape-markers';
import hash from 'object-hash';
import { createRef, useEffect, useState } from 'react';
import { GeoJSON, MapContainer, TileLayer } from 'react-leaflet';
import Parser from './parser/parser';

const parser = await Parser.instance();

const terminals = [10394, 10395, 10475, 10480, 10482, 10485, 10653, 10654, 10657, 10659, 10679, 11798, 11909, 12765];

function App() {
  const [selectedTerminal, setSelectedTerminal] = useState(terminals[0]);
  const [procedures, setProcedures] = useState<object[]>([]);

  const mapRef = createRef<Leaflet.Map>();
  const layerRef = createRef<Leaflet.GeoJSON>();

  useEffect(() => {
    (async () => {
      setProcedures(await parser.parse(selectedTerminal));
    })();
  }, [selectedTerminal]);

  useEffect(() => {
    if (layerRef.current && mapRef.current) {
      mapRef.current.flyToBounds(layerRef.current.getBounds(), {
        animate: false,
        padding: [50, 50],
      });
    }
  });

  return (
    <div style={{ display: 'flex', height: '100vh', width: '100vw' }}>
      <MapContainer
        center={[51.505, -0.09]}
        zoom={13}
        zoomSnap={0}
        zoomDelta={0.1}
        wheelPxPerZoomLevel={1000}
        style={{ height: '100%', width: '100%' }}
        ref={mapRef}
      >
        <TileLayer
          attribution='&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
          url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
        />
        {procedures.map((procedure) => (
          <>
            <GeoJSON
              key={hash(procedure ?? '') + 'lines'}
              data={procedure}
              style={({ properties }) => ({
                color: '#ff00ff',
                stroke: true,
                weight: 5,
                opacity: 1,
                dashArray: properties.isManual ? '20, 20' : undefined,
              })}
              filter={(feature) => feature.geometry.type !== 'Point'}
              ref={layerRef}
            />
            <GeoJSON
              key={hash(procedure ?? '') + 'points'}
              data={procedure}
              style={{
                color: 'black',
                fill: true,
                fillColor: 'transparent',
                stroke: true,
                weight: 3,
              }}
              pointToLayer={({ properties }, latlng) => {
                if (properties.isFlyOver)
                  return L.shapeMarker(latlng, {
                    shape: 'triangle',
                    radius: 6,
                  });
                if (properties.isIntersection) return L.circleMarker(latlng, { radius: 6 });

                return L.shapeMarker(latlng, {
                  shape: 'star-4',
                  radius: 10,
                  rotation: 45,
                });
              }}
              onEachFeature={({ geometry, properties }, layer) => {
                if (geometry.type === 'Point') {
                  layer.bindPopup(
                    `${properties.name}<br>
                ${properties.altitude} ft<br>
                ${properties.speed} kts<br>
                CNSTR: 
                ${properties.altitudeConstraint ?? ''}
                ${properties.speedConstraint ?? ''}<br>`
                  );
                }
              }}
              filter={(feature) => feature.geometry.type === 'Point'}
            />
          </>
        ))}
      </MapContainer>
      <div
        style={{
          overflowY: 'scroll',
          width: '200px',
        }}
      >
        <div
          style={{
            padding: '5px',
            display: 'flex',
            flexDirection: 'column',
            gap: '10px',
          }}
        >
          {terminals.map((terminal) => (
            <div
              key={terminal}
              style={{
                display: 'flex',
                flexDirection: 'column',
                background: '#eeeeee',
                border: selectedTerminal === terminal ? '1px solid black' : '1px solid #eeeeee',
                padding: '5px',
              }}
              onClick={() => setSelectedTerminal(terminal)}
            >
              <span style={{ whiteSpace: 'nowrap' }}>
                {(() => {
                  const t = parser.terminals.find(({ ID }) => ID === terminal);
                  return `${t?.ICAO} - ${t?.FullName}`;
                })()}
              </span>
              <pre>({terminal})</pre>
            </div>
          ))}
        </div>
      </div>
    </div>
  );
}

export default App;
