// ISO_PopulateRandomFootageIntoComp.jsx
// Artist: https://www.jasonfletcher.info/
// Code generated by GPT-5.6 Luna
// Date: August 14, 2026
// Description: This After Effects script will randomly select a footage clip from the "FootageTarget" folder (and its subfolders) and then add it to the active composition as the top-most layer. The footage will be stretched to fit the comp.

(function () {
    var undoGroupStarted = false;

    try {
        // ------------------------------------------------------------
        // Validate active composition
        // ------------------------------------------------------------
        var comp = app.project.activeItem;

        if (comp === null || !(comp instanceof CompItem)) {
            alert("Please open or select a composition before running this script.");
            return;
        }

        // ------------------------------------------------------------
        // Find the FootageTarget folder
        // ------------------------------------------------------------
        var footageTargetFolder = null;
        var i;

        for (i = 1; i <= app.project.numItems; i++) {
            var projectItem = app.project.item(i);

            if (projectItem !== null &&
                projectItem instanceof FolderItem &&
                projectItem.name === "FootageTarget") {
                footageTargetFolder = projectItem;
                break;
            }
        }

        if (footageTargetFolder === null) {
            alert('Could not find a project folder named "FootageTarget".');
            return;
        }

        // ------------------------------------------------------------
        // Recursively collect footage items
        // ------------------------------------------------------------
        var footageItems = [];

        function collectFootageItems(folder) {
            if (folder === null) {
                return;
            }

            var j;

            for (j = 1; j <= folder.numItems; j++) {
                var item = folder.item(j);

                if (item === null) {
                    continue;
                }

                if (item instanceof FolderItem) {
                    collectFootageItems(item);
                } else if (item instanceof FootageItem) {
                    // Only include actual imported footage/files.
                    // This excludes solid-color FootageItems.
                    if (item.mainSource !== null &&
                        item.mainSource.file !== null) {
                        footageItems.push(item);
                    }
                }
            }
        }

        collectFootageItems(footageTargetFolder);

        if (footageItems.length === 0) {
            alert('No usable footage clips were found inside "FootageTarget" or its subfolders.');
            return;
        }

        // ------------------------------------------------------------
        // Randomly select footage
        // ------------------------------------------------------------
        var randomIndex = Math.floor(Math.random() * footageItems.length);
        var selectedFootage = footageItems[randomIndex];

        if (selectedFootage === null) {
            alert("The randomly selected footage item could not be accessed.");
            return;
        }

        // ------------------------------------------------------------
        // Begin undo group
        // ------------------------------------------------------------
        app.beginUndoGroup("Add Random Footage From FootageTarget");
        undoGroupStarted = true;

        // ------------------------------------------------------------
        // Add footage as the top-most layer
        // ------------------------------------------------------------
        var newLayer = comp.layers.add(selectedFootage);

        if (newLayer === null) {
            throw new Error("After Effects could not add the selected footage to the composition.");
        }

        // ------------------------------------------------------------
        // Stretch independently in X/Y to exactly match comp size
        // ------------------------------------------------------------
        var sourceWidth = selectedFootage.width;
        var sourceHeight = selectedFootage.height;

        if (sourceWidth <= 0 || sourceHeight <= 0) {
            throw new Error("The selected footage has invalid dimensions.");
        }

        var scaleX = (comp.width / sourceWidth) * 100;
        var scaleY = (comp.height / sourceHeight) * 100;

        newLayer.transform.scale.setValue([scaleX, scaleY]);

        // ------------------------------------------------------------
        // Feedback
        // ------------------------------------------------------------
        alert(
            "Random footage added successfully.\n\n" +
            "Composition: " + comp.name + "\n" +
            "Footage: " + selectedFootage.name + "\n" +
            "Source Size: " + sourceWidth + " x " + sourceHeight + "\n" +
            "Comp Size: " + comp.width + " x " + comp.height + "\n" +
            "Scale X: " + scaleX.toFixed(2) + "%\n" +
            "Scale Y: " + scaleY.toFixed(2) + "%\n\n" +
            "Footage searched: " + footageItems.length + " clip(s)"
        );

    } catch (err) {
        alert(
            "The script encountered an error:\n\n" +
            (err !== null && err.message !== undefined ? err.message : err)
        );

    } finally {
        if (undoGroupStarted) {
            app.endUndoGroup();
        }
    }
})();