/**
 * Random Group Generator - Random Algorithms
 * Fisher-Yates Shuffle and other random functions
 */

// Fisher-Yates Shuffle Algorithm
function shuffle(array) {
    const arr = [...array];
    for (let i = arr.length - 1; i > 0; i--) {
        const j = Math.floor(Math.random() * (i + 1));
        [arr[i], arr[j]] = [arr[j], arr[i]];
    }
    return arr;
}

// Fisher-Yates Shuffle with custom random function (for seeded random)
function shuffleWithSeed(array, seed) {
    const arr = [...array];
    let random = seedRandom(seed);

    for (let i = arr.length - 1; i > 0; i--) {
        const j = Math.floor(random() * (i + 1));
        [arr[i], arr[j]] = [arr[j], arr[i]];
    }
    return arr;
}

// Seeded random number generator
function seedRandom(seed) {
    let s = seed || 1;
    return function() {
        s = Math.sin(s * 9999) * 10000;
        return s - Math.floor(s);
    };
}

// Generate random groups
function generateGroups(names, groupCount) {
    if (!names || names.length === 0) return [];

    const shuffled = shuffle(names);
    const groups = Array.from({ length: groupCount }, () => []);

    shuffled.forEach((name, index) => {
        groups[index % groupCount].push(name);
    });

    // Remove empty groups
    return groups.filter(group => group.length > 0);
}

// Generate groups by people per group
function generateGroupsByPeoplePerGroup(names, peoplePerGroup) {
    if (!names || names.length === 0) return [];

    const shuffled = shuffle(names);
    const groupCount = Math.ceil(shuffled.length / peoplePerGroup);
    const groups = Array.from({ length: groupCount }, () => []);

    shuffled.forEach((name, index) => {
        groups[Math.floor(index / peoplePerGroup)].push(name);
    });

    return groups.filter(group => group.length > 0);
}

// Generate random order (shuffle only)
function generateRandomOrder(names) {
    return shuffle(names);
}

// Generate random pairs
function generateRandomPairs(names) {
    const shuffled = shuffle(names);
    const pairs = [];

    for (let i = 0; i < shuffled.length - 1; i += 2) {
        pairs.push([shuffled[i], shuffled[i + 1]]);
    }

    // If odd number, add remaining to last pair or single
    if (shuffled.length % 2 === 1) {
        pairs[pairs.length - 1].push(shuffled[shuffled.length - 1]);
    }

    return pairs;
}

// Pick random winner
function pickRandomWinner(names) {
    if (!names || names.length === 0) return null;
    const randomIndex = Math.floor(Math.random() * names.length);
    return names[randomIndex];
}

// Get random leader from group
function getRandomLeader(group) {
    if (!group || group.length === 0) return null;
    const randomIndex = Math.floor(Math.random() * group.length);
    return group[randomIndex];
}

// Calculate statistics
function calculateStats(names, groups) {
    const totalNames = names.length;
    const groupCount = groups.length;
    const avgPerGroup = groupCount > 0 ? (totalNames / groupCount).toFixed(1) : 0;

    return {
        totalNames,
        groupCount,
        avgPerGroup: parseFloat(avgPerGroup)
    };
}

// Shuffle animation helper
function shuffleArrayWithAnimation(array, duration = 1000, callback) {
    const result = [...array];
    const startTime = Date.now();

    function animate() {
        const elapsed = Date.now() - startTime;
        const progress = Math.min(elapsed / duration, 1);

        // Perform multiple quick shuffles during animation
        if (progress < 1) {
            for (let i = 0; i < 5; i++) {
                const idx1 = Math.floor(Math.random() * result.length);
                const idx2 = Math.floor(Math.random() * result.length);
                [result[idx1], result[idx2]] = [result[idx2], result[idx1]];
            }
            callback(result, progress);
            requestAnimationFrame(animate);
        } else {
            // Final proper shuffle
            const finalResult = shuffle(array);
            callback(finalResult, 1);
        }
    }

    animate();
}

// Wheel spin calculation
function calculateWheelSpin(currentRotation, names) {
    const segmentAngle = 360 / names.length;
    const winnerIndex = Math.floor(Math.random() * names.length);
    const extraSpins = 5 + Math.floor(Math.random() * 5); // 5-10 full spins
    const targetAngle = winnerIndex * segmentAngle + (segmentAngle / 2);
    const totalRotation = currentRotation + (extraSpins * 360) + (360 - (currentRotation % 360)) + targetAngle;

    return {
        rotation: totalRotation,
        winner: names[winnerIndex],
        winnerIndex
    };
}

// Export functions
if (typeof module !== 'undefined' && module.exports) {
    module.exports = {
        shuffle,
        shuffleWithSeed,
        generateGroups,
        generateGroupsByPeoplePerGroup,
        generateRandomOrder,
        generateRandomPairs,
        pickRandomWinner,
        getRandomLeader,
        calculateStats,
        shuffleArrayWithAnimation,
        calculateWheelSpin
    };
}

