var __rest = (this && this.__rest) || function (s, e) {
    var t = {};
    for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
        t[p] = s[p];
    if (s != null && typeof Object.getOwnPropertySymbols === "function")
        for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
            if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
                t[p[i]] = s[p[i]];
        }
    return t;
};
import { useTexture, useFrame, invalidate, } from '../../modules/three';
import Arc from '../Arc/Arc';
import Location from '../Location/Location';
import React, { forwardRef, useEffect, 
// useLayoutEffect,
useRef, useState, } from 'react';
import { AdditiveBlending, BackSide, Color } from 'three';
import { animated as a } from '@react-spring/three';
// import MarkersInstance, {MarkerHandle} from '../MarkerInstance/MarkerInstance';
import gsap from 'gsap';
import Marker from '../Marker/Marker';
const Halo = ({ themeColor }) => {
    return (React.createElement("mesh", { renderOrder: -2 },
        React.createElement("sphereGeometry", { args: [1.08, 32, 32] }),
        React.createElement("shaderMaterial", { attach: 'material', side: BackSide, transparent: true, 
            // depthTest={false}
            depthWrite: false, blending: AdditiveBlending, uniforms: {
                amountBorder: { value: 1.2 },
                alpha: { value: 1 },
                color: { value: new Color(themeColor) },
            }, key: Math.random() * 100, vertexShader: vertexShader, fragmentShader: fragmentShader })));
};
export default forwardRef(function Globe(_a, ref) {
    var { locations = [], currentLocation, beams = [], isRevealed, panRotation = [0, 0], isTransitioning, isVisible, children, isSender, showBeams, globeTheme } = _a, props = __rest(_a, ["locations", "currentLocation", "beams", "isRevealed", "panRotation", "isTransitioning", "isVisible", "children", "isSender", "showBeams", "globeTheme"]);
    const inner = useRef(null);
    const arcsRef = useRef([]);
    const markersRef = useRef([]);
    const [rotation, setRotation] = useState([0, 0]);
    const [isAdultTheme, setIsAdultTheme] = useState(false);
    const [themeColor, setThemeColor] = useState(0x91b8c8);
    const materialProps = useTexture({
        map: isAdultTheme
            ? require('../../assets/images/globe-displacement-map.jpg')
            : require('../../assets/images/globe-albedo.jpg'),
        normalMap: require('../../assets/images/globe-normal-map.jpg'),
        aoMap: require('../../assets/images/globe-ao-map.jpg'),
        displacementMap: require('../../assets/images/globe-displacement-map.jpg'),
    });
    useEffect(() => {
        setRotation(([x, y]) => [x, y + panRotation[0]]);
    }, [panRotation]);
    useEffect(() => {
        const tl = gsap.timeline({
            repeat: -1,
            onUpdate: () => {
                invalidate();
            },
        });
        if (showBeams) {
            const i = { value: 0 };
            tl.set(i, { value: 0 });
            tl.set(arcsRef.current, { progress: 0.1 });
            tl.to(arcsRef.current, {
                progress: 0.4,
                ease: 'linear',
                duration: 2,
                stagger: {
                    amount: 1,
                    onStart: () => {
                        if (!isSender) {
                            markersRef.current[i.value].appear();
                            i.value += 1;
                        }
                    },
                    onComplete: () => {
                        if (isSender) {
                            markersRef.current[i.value].impact();
                            i.value += 1;
                        }
                    },
                },
            });
            tl.set(i, { value: 0 });
            tl.set(arcsRef.current, { progress: 0.6 });
            tl.to(arcsRef.current, {
                progress: 0.8,
                delay: 3,
                ease: 'linear',
                duration: 0.8,
                stagger: {
                    amount: 1,
                    onStart: () => {
                        if (!isSender) {
                            markersRef.current[i.value].vanish();
                            i.value += 1;
                        }
                    },
                    onComplete: () => {
                        if (isSender) {
                            markersRef.current[i.value].vanish();
                            i.value += 1;
                        }
                    },
                },
            });
        }
        return () => {
            tl.revert();
        };
    }, [beams, locations, isSender, showBeams]);
    useEffect(() => {
        if (isVisible && isTransitioning) {
            setRotation([0, 0]);
            inner.current.rotation.x = 0;
            inner.current.rotation.y = 0;
        }
    }, [isVisible, isTransitioning]);
    useEffect(() => {
        if (showBeams) {
            return;
        }
        if (arcsRef.current.length) {
            arcsRef.current.forEach(m => m && m.revert());
        }
        markersRef.current.forEach(m => m && m.vanish());
    }, [showBeams]);
    useEffect(() => {
        if (globeTheme === 'adult') {
            setIsAdultTheme(true);
            setThemeColor(0x888888);
        }
    }, [globeTheme]);
    /* Raf
    --------------------------------------------------------- */
    useFrame((_state, delta) => {
        if (isRevealed && !isTransitioning) {
            inner.current.rotation.y -= 0.3 * delta;
        }
    });
    return (React.createElement(a.group, Object.assign({}, props, { ref: ref }),
        React.createElement(a.group, { rotation: [0, rotation[1], 0] },
            React.createElement(a.group, { ref: inner, rotation: [rotation[0], 0, 0] },
                React.createElement("mesh", { receiveShadow: true, castShadow: true },
                    React.createElement("sphereGeometry", { args: [1, 512, 512] }),
                    React.createElement("meshPhysicalMaterial", Object.assign({ roughness: 0.6, metalness: 0, envMapIntensity: 0.3, aoMapIntensity: 0.5, normalScale: [0.5, 0.5], displacementScale: 0.06, displacementBias: -0.01 }, materialProps))),
                children,
                currentLocation !== undefined && (React.createElement(Location, { coordinates: currentLocation.coordinates, isCurrentLocation: true })),
                locations.map((location, i) => {
                    return (React.createElement(Marker, { location: location, ref: el => (markersRef.current[i] = el), key: `marker_${i}` }));
                }),
                beams &&
                    beams.map((l, i) => {
                        return (React.createElement(Arc, { start: l.start, end: l.end, ref: el => (arcsRef.current[i] = el), key: `arc_${i}` }));
                    }))),
        React.createElement(Halo, { themeColor: themeColor })));
});
const vertexShader = /*glsl*/ `
  varying vec3 worldNormal;
  varying vec3 viewDirection;

  void main() {
      vec3 transformed = position;

      vec4 worldPos = modelMatrix * vec4(transformed, 1.);
      worldNormal   = normalize(modelMatrix * vec4(normal, 0.)).xyz;
      viewDirection = normalize(worldPos.xyz - cameraPosition);

      gl_Position = projectionMatrix * modelViewMatrix * vec4(transformed, 1.0);
  }
`;
const fragmentShader = /*glsl*/ `
  uniform float amountBorder;
  uniform float alpha;
  uniform vec3 color;

  varying vec3 worldNormal;
  varying vec3 viewDirection;


  float fresnel(vec3 viewDirection, vec3 worldNormal) {
      return pow( 1.0 - dot( viewDirection, worldNormal), amountBorder );
  }


  void main() {
      vec3 col = vec3(0);

      float a = fresnel(viewDirection, worldNormal);
      a = smoothstep(1., .5, a);
      a = pow(a, 3.);
      a *= alpha;

      col = color;

      if (a <= 0.001) discard;

      gl_FragColor = vec4(col, a);
  }

`;
