<template>
    <div class="balance">
        <svg
            class="scale-svg"
            viewBox="0 0 720 320"
            preserveAspectRatio="xMidYMid meet"
        >
            <!-- Stationary structure -->
            <polygon
                points="338,162 382,162 360,108"
                fill="rgba(255,255,255,0.55)"
            />

            <!-- Rotating assembly: beam + hang lines + pans + dots -->
            <g :style="beamStyle">
                <!-- Beam -->
                <line
                    x1="80"
                    y1="110"
                    x2="640"
                    y2="110"
                    stroke="rgba(255,255,255,0.72)"
                    stroke-width="4"
                    stroke-linecap="round"
                />
                <!-- Hang lines -->
                <line
                    x1="140"
                    y1="110"
                    x2="140"
                    y2="165"
                    stroke="rgba(255,255,255,0.35)"
                    stroke-width="1.5"
                />
                <line
                    x1="580"
                    y1="110"
                    x2="580"
                    y2="165"
                    stroke="rgba(255,255,255,0.35)"
                    stroke-width="1.5"
                />

                <!-- Left pan (humans) -->
                <rect
                    x="80"
                    y="165"
                    width="120"
                    height="55"
                    rx="3"
                    fill="rgba(255,255,255,0.04)"
                    stroke="rgba(255,255,255,0.32)"
                    stroke-width="1"
                />
                <circle
                    v-for="(p, i) in leftDots"
                    :key="`h${i}`"
                    :cx="p.x"
                    :cy="p.y"
                    r="3.2"
                    class="dot human-dot"
                />

                <!-- Right pan (machines) -->
                <rect
                    x="520"
                    y="165"
                    width="120"
                    height="55"
                    rx="3"
                    fill="rgba(255,255,255,0.04)"
                    stroke="rgba(255,255,255,0.32)"
                    stroke-width="1"
                />
                <circle
                    v-for="(p, i) in rightDots"
                    :key="`b${i}`"
                    :cx="p.x"
                    :cy="p.y"
                    r="3.2"
                    class="dot bot-dot"
                />
            </g>
        </svg>
    </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, onBeforeUnmount } from "vue";
import { useIsSlideActive } from "@slidev/client";

const humanCount = ref(7);
const botCount = ref(7);

const diff = computed(() => botCount.value - humanCount.value);
// Positive tilt = right side down (machines heavier).
const tilt = computed(() => Math.max(-18, Math.min(18, diff.value * 1.25)));

const beamStyle = computed(() => ({
    transformOrigin: "360px 110px",
    transform: `rotate(${tilt.value}deg)`,
    transition: "transform 0.7s cubic-bezier(.3,.7,.4,1.2)",
}));

const COLS = 12;
const SPACING = 9;

function panPositions(count: number, panLeftX: number) {
    const positions: { x: number; y: number }[] = [];
    for (let i = 0; i < count; i++) {
        const row = Math.floor(i / COLS);
        const col = i % COLS;
        positions.push({
            x: panLeftX + 12 + col * SPACING,
            y: 211 - row * SPACING,
        });
    }
    return positions;
}

const leftDots = computed(() => panPositions(humanCount.value, 80));
const rightDots = computed(() => panPositions(botCount.value, 520));

let timers: ReturnType<typeof setTimeout>[] = [];

function teardown() {
    timers.forEach((t) => clearTimeout(t));
    timers = [];
    humanCount.value = 7;
    botCount.value = 7;
}

function kickoff() {
    teardown();

    // Phase 1: 5 cycles of (+1 human, +2 bots). Both sides grow, bots faster.
    // Phase 2: humans stop; bots cascade.
    type Ev = { t: number; type: "h" | "b" };
    const events: Ev[] = [
        // Cycle 1
        { t: 500,  type: "h" },
        { t: 800,  type: "b" }, { t: 870,  type: "b" },
        // Cycle 2
        { t: 1350, type: "h" },
        { t: 1650, type: "b" }, { t: 1720, type: "b" },
        // Cycle 3
        { t: 2200, type: "h" },
        { t: 2500, type: "b" }, { t: 2570, type: "b" },
        // Cycle 4
        { t: 3000, type: "h" },
        { t: 3300, type: "b" }, { t: 3370, type: "b" },
        // Cycle 5
        { t: 3800, type: "h" },
        { t: 4100, type: "b" }, { t: 4170, type: "b" },
        // Phase 2: bot cascade
        { t: 4450, type: "b" }, { t: 4510, type: "b" },
        { t: 4720, type: "b" }, { t: 4780, type: "b" },
        { t: 4950, type: "b" }, { t: 5010, type: "b" },
        { t: 5150, type: "b" }, { t: 5210, type: "b" },
        { t: 5320, type: "b" }, { t: 5380, type: "b" },
        { t: 5470, type: "b" }, { t: 5530, type: "b" },
    ];

    for (const e of events) {
        timers.push(
            setTimeout(() => {
                if (e.type === "h") humanCount.value += 1;
                else botCount.value += 1;
            }, e.t),
        );
    }
}

const isActive = useIsSlideActive();
watch(
    isActive,
    (active) => {
        if (active) kickoff();
        else teardown();
    },
    { immediate: true },
);

onBeforeUnmount(teardown);
</script>

<style scoped>
.balance {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1.1rem;
    width: 100%;
    max-width: 44rem;
    margin: 0 auto;
}

.scale-svg {
    width: 100%;
    height: auto;
    max-height: 21rem;
}

.dot {
    animation: dot-pop 0.32s cubic-bezier(0.2, 0.7, 0.3, 1.45) both;
    transform-box: fill-box;
    transform-origin: center;
}
.human-dot {
    fill: #ffffff;
    filter: drop-shadow(0 0 3px rgba(255, 255, 255, 0.45));
}
.bot-dot {
    fill: #ff5a5a;
    filter: drop-shadow(0 0 3px rgba(255, 90, 90, 0.6));
}

@keyframes dot-pop {
    0% {
        opacity: 0;
        transform: translateY(-7px) scale(0.5);
    }
    100% {
        opacity: 1;
        transform: translateY(0) scale(1);
    }
}
</style>
