/**
 * Wild Dragon MAM - Premiere Pro ExtendScript
 *
 * This file runs in the Premiere Pro host context (not the browser panel).
 * It is registered via <ScriptPath> in manifest.xml and called from the
 * panel via csInterface.evalScript().
 *
 * ExtendScript is ES3-level JavaScript — no arrow functions, no const/let,
 * no template literals, no destructuring.
 */

// ============================================================================
// Core Import Functions
// ============================================================================

/**
 * Imports a media file into the active Premiere Pro project.
 * @param {string} filePath - Full path to the file to import
 * @returns {string} JSON string with success status and message
 */
function importFileToProject(filePath) {
    var result = {
        success: false,
        message: "",
        itemID: null
    };

    try {
        if (!app.project) {
            result.message = "No active Premiere Pro project";
            return JSON.stringify(result);
        }

        var file = new File(filePath);
        if (!file.exists) {
            result.message = "File does not exist: " + filePath;
            return JSON.stringify(result);
        }

        app.project.importFiles([filePath]);

        result.success = true;
        result.message = "File imported successfully";
        return JSON.stringify(result);
    } catch (error) {
        result.message = "Error importing file: " + error.message;
        return JSON.stringify(result);
    }
}

/**
 * Gets the active sequence in the project.
 * @returns {string} JSON string with sequence name and ID, or nulls
 */
function getActiveSequence() {
    var result = {
        sequenceName: null,
        sequenceID: null
    };

    try {
        if (!app.project) return JSON.stringify(result);

        var activeSequence = app.project.activeSequence;
        if (activeSequence) {
            result.sequenceName = activeSequence.name;
            result.sequenceID   = activeSequence.sequenceID;
        }
        return JSON.stringify(result);
    } catch (error) {
        return JSON.stringify(result);
    }
}

/**
 * Inserts a clip into the active sequence at the playhead position.
 * @param {string} filePath   - Full path to the media file
 * @param {number} trackIndex - Video track index (1-based)
 * @returns {string} JSON string with success status
 */
function insertClipToSequence(filePath, trackIndex) {
    var result = {
        success: false,
        message: ""
    };

    try {
        if (!app.project) {
            result.message = "No active project";
            return JSON.stringify(result);
        }

        var sequence = app.project.activeSequence;
        if (!sequence) {
            result.message = "No active sequence";
            return JSON.stringify(result);
        }

        app.project.importFiles([filePath]);

        var file = new File(filePath);
        var fileName = file.displayName;
        var rootBin = app.project.rootItem;
        var projectItem = findProjectItemByName(rootBin, fileName);

        if (!projectItem) {
            result.message = "Could not find imported file in project";
            return JSON.stringify(result);
        }

        if (trackIndex < 1 || trackIndex > sequence.videoTracks.numTracks) {
            result.message = "Invalid track index: " + trackIndex;
            return JSON.stringify(result);
        }

        var track = sequence.videoTracks[trackIndex - 1];
        var playheadTime = sequence.getPlayerPosition();
        var trackItem = track.insertClip(projectItem, playheadTime);

        if (trackItem) {
            result.success = true;
            result.message = "Clip inserted at track " + trackIndex;
        } else {
            result.message = "Failed to insert clip into track";
        }

        return JSON.stringify(result);
    } catch (error) {
        result.message = "Error inserting clip: " + error.message;
        return JSON.stringify(result);
    }
}

/**
 * Gets the current project file path.
 * @returns {string} JSON string with project path and name
 */
function getProjectPath() {
    var result = {
        projectPath: null,
        projectName: null
    };

    try {
        if (!app.project) return JSON.stringify(result);

        result.projectPath = app.project.path;
        result.projectName = app.project.name;
        return JSON.stringify(result);
    } catch (error) {
        return JSON.stringify(result);
    }
}

/**
 * Gets information about all video tracks in the active sequence.
 * @returns {string} JSON string with an array of track objects
 */
function getSequenceTracks() {
    var result = { tracks: [] };

    try {
        if (!app.project) return JSON.stringify(result);

        var sequence = app.project.activeSequence;
        if (!sequence) return JSON.stringify(result);

        for (var i = 0; i < sequence.videoTracks.numTracks; i++) {
            var track = sequence.videoTracks[i];
            result.tracks.push({
                index: i + 1,
                name:  track.name || ("V" + (i + 1)),
                type:  "video"
            });
        }
        return JSON.stringify(result);
    } catch (error) {
        return JSON.stringify(result);
    }
}

/**
 * Gets the current playhead position in the active sequence.
 * @returns {string} JSON string with timeInSeconds and SMPTE timeCode
 */
function getPlayheadPosition() {
    var result = {
        timeInSeconds: 0,
        timeCode: ""
    };

    try {
        if (!app.project) return JSON.stringify(result);

        var sequence = app.project.activeSequence;
        if (!sequence) return JSON.stringify(result);

        var time   = sequence.getPlayerPosition();
        var ticks  = parseFloat(time.ticks);
        // Premiere Pro ticks: 254016000000 ticks per second
        var TICKS_PER_SECOND = 254016000000;
        var totalSeconds = ticks / TICKS_PER_SECOND;
        result.timeInSeconds = totalSeconds;

        // Build SMPTE timecode — use sequence frame rate
        var frameRate   = sequence.timebase ? (TICKS_PER_SECOND / parseFloat(sequence.timebase)) : 25;
        var totalFrames = Math.floor(totalSeconds * frameRate);
        var hours   = Math.floor(totalFrames / (frameRate * 3600));
        var minutes = Math.floor((totalFrames % (frameRate * 3600)) / (frameRate * 60));
        var seconds = Math.floor((totalFrames % (frameRate * 60))  / frameRate);
        var frames  = totalFrames % Math.round(frameRate);

        result.timeCode = pad(hours, 2) + ":" + pad(minutes, 2) + ":" +
                          pad(seconds, 2) + ":" + pad(frames, 2);
        return JSON.stringify(result);
    } catch (error) {
        return JSON.stringify(result);
    }
}

/**
 * Gets basic project information.
 * @returns {string} JSON string with project name, path, and sequence count
 */
function getProjectInfo() {
    var result = {
        projectName: "",
        projectPath: "",
        sequenceCount: 0
    };

    try {
        if (!app.project) return JSON.stringify(result);

        result.projectName = app.project.name;
        result.projectPath = app.project.path;

        var rootBin = app.project.rootItem;
        if (rootBin && rootBin.children) {
            for (var i = 0; i < rootBin.children.numItems; i++) {
                if (rootBin.children[i].type === ProjectItemType.SEQUENCE) {
                    result.sequenceCount++;
                }
            }
        }
        return JSON.stringify(result);
    } catch (error) {
        return JSON.stringify(result);
    }
}

/**
 * Exports the current sequence using Adobe Media Encoder.
 *
 * AME must be installed. This function launches AME (if not already running)
 * and queues the export job — it returns immediately; encoding happens in the
 * background and the output file appears when AME finishes.
 *
 * @param {string} outputPath  - Absolute path for the output file
 * @param {string} presetPath  - Absolute path to an AME preset file (.epr);
 *                               pass an empty string to use the sequence's
 *                               current export settings.
 * @returns {string} JSON string with success flag, message, and jobId
 */
function exportSequence(outputPath, presetPath) {
    var result = {
        success: false,
        message: "",
        jobId: null
    };

    try {
        if (!app.project) {
            result.message = "No active project";
            return JSON.stringify(result);
        }

        var sequence = app.project.activeSequence;
        if (!sequence) {
            result.message = "No active sequence";
            return JSON.stringify(result);
        }

        // Ensure Adobe Media Encoder is running before queuing
        app.encoder.launchEncoder();

        // encodeSequence(sequence, outputFilePath, presetPath, workAreaType, removeOnCompletion)
        // workAreaType: ENCODE_ENTIRE = 0, ENCODE_IN_TO_OUT = 1
        var jobId = app.encoder.encodeSequence(
            sequence,
            outputPath,
            presetPath || "",
            app.encoder.ENCODE_ENTIRE,
            false  // keep job in AME queue after completion
        );

        if (jobId) {
            result.success = true;
            result.message = "Export queued in Adobe Media Encoder";
            result.jobId   = jobId;
        } else {
            result.message = "AME returned no job ID — verify that the preset path is valid";
        }

        return JSON.stringify(result);
    } catch (error) {
        result.message = "Export error: " + error.message;
        return JSON.stringify(result);
    }
}

// ============================================================================
// Helper Functions
// ============================================================================

/**
 * Recursively searches for a project item by display name.
 * @param {ProjectItem} bin  - The bin/root to search
 * @param {string}      name - Name to match
 * @returns {ProjectItem|null}
 */
function findProjectItemByName(bin, name) {
    if (!bin || !bin.children) return null;

    for (var i = 0; i < bin.children.numItems; i++) {
        var item = bin.children[i];
        if (item.name === name) return item;
        if (item.type === ProjectItemType.BIN) {
            var found = findProjectItemByName(item, name);
            if (found) return found;
        }
    }
    return null;
}

/**
 * Pads a number with leading zeros.
 * @param {number} num    - Number to pad
 * @param {number} digits - Minimum digit count
 * @returns {string}
 */
function pad(num, digits) {
    var str = "" + Math.floor(num);
    while (str.length < digits) str = "0" + str;
    return str;
}
