import React, { useEffect } from "react";
import { View } from "react-native";
import Svg, { Path } from "react-native-svg";
import Animated, { Easing, ReduceMotion, useAnimatedStyle, useSharedValue, withDelay, withRepeat, withSequence, withTiming, } from "react-native-reanimated";
import { useColorScheme } from "nativewind";
import { ENTROPY_MARK_ASPECT, ENTROPY_MARK_PATH, ENTROPY_MARK_STEP, ENTROPY_MARK_VIEWBOX, } from "./entropy-mark-geometry";
// React Native port of the website's animated company mark
// (website/src/components/logo.tsx). Same motion model, hover → touch:
//
//  • At rest the mark is FLAT — sharp source `>_` only, echoes collapsed
//    underneath it (invisible).
//  • While pressed, `open` eases 0→1: the three grey time-echoes fade in and
//    drift apart, each breathing on its own period/phase so they never move
//    in lockstep (the endless, unevenly-spaced cascade).
//  • Parallax: while pressed, the echoes lean toward the finger (deeper
//    echoes shift more = depth), gated by `open` so it fades with collapse.
//  • On release, `open` eases 1→0 and the echoes resolve cleanly back into
//    the source — no snap.
//  • The sharp source NEVER moves (anchored), and each echo lives on its own
//    Animated.View layer so the source is never re-rasterized mid-animation
//    (the compositor lesson from the web version).
//
// Honors the system reduce-motion setting via ReduceMotion.System.
// echo keyed by depth (3 = furthest/dimmest .. 1 = nearest the source)
const PALETTE = {
    light: {
        src: "#000000",
        echo: { 3: "#f5f5f5", 2: "#e2e2e2", 1: "#cbcbcb" },
        cyan: "#0096aa",
        red: "#c82837",
    },
    dark: {
        src: "#ffffff",
        echo: { 3: "#373737", 2: "#5f5f5f", 1: "#8c8c8c" },
        cyan: "#268ca0",
        red: "#a53440",
    },
};
// Matches the web component: breathing reach per echo depth, parallax px per
// depth-step, breathing period 2.6+i*0.7s with staggered phase.
const AMP = { 3: 1.55, 2: 1.4, 1: 1.6 };
const PX = 9;
const PY = 7;
function Echo({ depth, fill, open, px, py, width, height, }) {
    // Breathing oscillator 0..1, own period + phase per depth → desynced.
    const breath = useSharedValue(0);
    useEffect(() => {
        const half = ((2.6 + depth * 0.7) * 1000) / 2;
        const ease = Easing.inOut(Easing.sin);
        breath.value = withDelay(depth * 400, withRepeat(withSequence(withTiming(1, { duration: half, easing: ease, reduceMotion: ReduceMotion.System }), withTiming(0, { duration: half, easing: ease, reduceMotion: ReduceMotion.System })), -1, false, undefined, ReduceMotion.System));
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [depth]);
    const style = useAnimatedStyle(() => {
        // Offset = base drift * breathing multiplier (1..AMP) + parallax lean,
        // all scaled by `open` so rest = exactly collapsed under the source.
        const m = 1 + (AMP[depth] - 1) * breath.value;
        const tx = depth * ENTROPY_MARK_STEP.x * open.value * m + depth * PX * px.value * open.value;
        const ty = depth * ENTROPY_MARK_STEP.y * open.value * m + depth * PY * py.value * open.value;
        return {
            opacity: open.value,
            transform: [{ translateX: tx }, { translateY: ty }],
        };
    });
    return (<Animated.View style={[{ position: "absolute", width, height, pointerEvents: "none" }, style]}>
      <Svg width={width} height={height} viewBox={ENTROPY_MARK_VIEWBOX}>
        <Path d={ENTROPY_MARK_PATH} fillRule="evenodd" fill={fill}/>
      </Svg>
    </Animated.View>);
}
/**
 * Touch-interactive company `>_` mark — flat at rest, echo-cascade + parallax
 * while pressed, clean collapse on release. The RN twin of the website logo.
 */
export function EntropyMarkAnimated({ size = 28, variant = "mono", scheme, active = false, animateOnPress = true, }) {
    const { colorScheme } = useColorScheme();
    const p = PALETTE[scheme ?? (colorScheme === "dark" ? "dark" : "light")];
    const width = Math.round(size * ENTROPY_MARK_ASPECT);
    const open = useSharedValue(active ? 1 : 0);
    const px = useSharedValue(0);
    const py = useSharedValue(0);
    useEffect(() => {
        open.value = withTiming(active ? 1 : 0, {
            duration: 450,
            easing: Easing.out(Easing.cubic),
            reduceMotion: ReduceMotion.System,
        });
        // eslint-disable-next-line react-hooks/exhaustive-deps
    }, [active]);
    const track = (e) => {
        // Normalize finger position over the mark to -1..1 (parallax input).
        const nx = Math.max(-1, Math.min(1, (e.nativeEvent.locationX / width - 0.5) * 2));
        const ny = Math.max(-1, Math.min(1, (e.nativeEvent.locationY / size - 0.5) * 2));
        px.value = withTiming(nx, { duration: 80, reduceMotion: ReduceMotion.System });
        py.value = withTiming(ny, { duration: 80, reduceMotion: ReduceMotion.System });
    };
    const press = (down) => (e) => {
        if (!animateOnPress) {
            return;
        }
        if (down) {
            track(e);
            open.value = withTiming(1, {
                duration: 450,
                easing: Easing.out(Easing.cubic),
                reduceMotion: ReduceMotion.System,
            });
        }
        else {
            // Release: echoes resolve back into the source, parallax recenters.
            open.value = withTiming(active ? 1 : 0, {
                duration: 500,
                easing: Easing.inOut(Easing.cubic),
                reduceMotion: ReduceMotion.System,
            });
            px.value = withTiming(0, { duration: 500, reduceMotion: ReduceMotion.System });
            py.value = withTiming(0, { duration: 500, reduceMotion: ReduceMotion.System });
        }
    };
    const chromaStyle = useAnimatedStyle(() => ({ opacity: open.value }));
    return (<View style={{ width, height: size }} onStartShouldSetResponder={() => animateOnPress} onResponderGrant={press(true)} onResponderMove={track} onResponderRelease={press(false)} onResponderTerminate={press(false)}>
      {/* echoes: far (dim) → near, each on its own compositor layer */}
      {[3, 2, 1].map((i) => (<Echo key={i} depth={i} fill={p.echo[i]} open={open} px={px} py={py} width={width} height={size}/>))}

      {/* chroma fringe — rides `open` (sharp offset; RN SVG has no cheap blur) */}
      {variant === "chroma" ? (<Animated.View style={[
                { position: "absolute", width, height: size, pointerEvents: "none" },
                chromaStyle,
            ]}>
          <Svg width={width} height={size} viewBox={ENTROPY_MARK_VIEWBOX}>
            <Path d={ENTROPY_MARK_PATH} fillRule="evenodd" fill={p.cyan} opacity={0.5} transform="translate(10 8)"/>
            <Path d={ENTROPY_MARK_PATH} fillRule="evenodd" fill={p.red} opacity={0.45} transform="translate(-10 -8)"/>
          </Svg>
        </Animated.View>) : null}

      {/* sharp source — always visible, never moves (anchored). Absolutely
            positioned + last in the tree so it paints ON TOP of the absolutely-
            positioned echo/chroma layers on web too: CSS paints positioned
            siblings above static ones regardless of DOM order, so a static
            source would otherwise be buried under the echoes on web. */}
      <View style={{ position: "absolute", width, height: size, pointerEvents: "none" }}>
        <Svg width={width} height={size} viewBox={ENTROPY_MARK_VIEWBOX}>
          <Path d={ENTROPY_MARK_PATH} fillRule="evenodd" fill={p.src}/>
        </Svg>
      </View>
    </View>);
}
export default EntropyMarkAnimated;
//# sourceMappingURL=entropy-mark-animated.jsx.map