import { ComputedScores, RawScores, RoarRun, InteractionEvent, TrialData } from './run';
import { TaskVariantInfo, RoarTaskVariant } from './task';
import { UserInfo, UserUpdateInput, RoarAppUser } from './user';
import { FirebaseProject, OrgLists } from '../../interfaces';
import { FirebaseConfig } from '../util';
import { JSONSchemaType } from 'ajv/dist/2020';
interface DataFlags {
    user?: boolean;
    task?: boolean;
    variant?: boolean;
    run?: boolean;
}
export interface AppkitInput {
    firebaseProject?: FirebaseProject;
    firebaseConfig?: FirebaseConfig;
    userInfo: UserInfo;
    taskInfo: TaskVariantInfo;
    assigningOrgs?: OrgLists;
    readOrgs?: OrgLists;
    assignmentId?: string;
    runId?: string;
    testData?: DataFlags;
    demoData?: DataFlags;
}
/**
 * The RoarAppkit class is the main entry point for ROAR apps using the ROAR
 * Firestore API.  It represents multiple linked Firestore documents and
 * provides methods for interacting with them.
 */
export declare class RoarAppkit {
    firebaseProject?: FirebaseProject;
    firebaseConfig?: FirebaseConfig;
    run?: RoarRun;
    task?: RoarTaskVariant;
    user?: RoarAppUser;
    testData: DataFlags;
    demoData: DataFlags;
    private _userInfo;
    private _taskInfo;
    private _assigningOrgs?;
    private _readOrgs?;
    private _assignmentId?;
    private _runId?;
    private _authenticated;
    private _initialized;
    private _started;
    private _uploadQueue;
    private _storageBucket?;
    /**
     * Create a RoarAppkit.
     *
     * @param {AppkitInput} input
     * @param {UserInfo} input.userInfo - The user input object
     * @param {TaskVariantInfo} input.taskInfo - The task input object
     * @param {OrgLists} input.assigningOrgs - The IDs of the orgs to which this run belongs
     * @param {OrgLists} input.readOrgs - The IDs of the orgs that can read this run
     * @param {string} input.assignmentId - The ID of the assignment this run belongs to
     * @param {string} input.runId - The ID of the run. If undefined, a new run will be created.
     * @param {DataFlags} input.testData - Boolean flags indicating whether the user, task, or run are test data
     * @param {DataFlags} input.demoData - Boolean flags indicating whether the user, task, or run are demo data
     */
    constructor({ firebaseProject, firebaseConfig, userInfo, taskInfo, assigningOrgs, readOrgs, assignmentId, runId, testData, demoData, }: AppkitInput);
    /**
     * Initializes the storage bucket for recording uploads.
     * Resolves the bucket URL from the Firebase project ID using the BUCKET_URLS constant map.
     * @throws {Error} If the project ID does not map to a known storage bucket.
     */
    private _initStorageBucket;
    private _init;
    get authenticated(): boolean;
    /**
     * Update the user's data (both locally and in Firestore).
     * @param {object} input
     * @param {string[]} input.tasks - The tasks to be added to the user doc
     * @param {string[]} input.variants - The variants to be added to the user doc
     * @param {string} input.assessmentPid - The assessment PID of the user
     * @param {*} input.userMetadata - Any additional user metadata
     * @method
     * @async
     */
    updateUser({ tasks, variants, assessmentPid, ...userMetadata }: UserUpdateInput): Promise<void>;
    /**
     * Start the ROAR run. Push the task and run info to Firestore.
     * Call this method before starting the jsPsych experiment.
     * @method
     * @async
     */
    startRun(additionalRunMetadata?: {
        [key: string]: string;
    }): Promise<boolean>;
    /**
     * Validate the task variant parameters against a given JSON schema.
     *
     * This method uses the AJV library to validate the `variantParams` from the task information
     * against the provided JSON schema. If the parameters are invalid, it throws an error with
     * detailed messages for each validation error.
     *
     * @param {JSONSchemaType<unknown>} parameterSchema - The JSON schema to validate the parameters against.
     * @throws {Error} Throws an error if the parameters are invalid, including detailed validation error messages.
     */
    validateParameters(parameterSchema: JSONSchemaType<unknown>): Promise<void>;
    /**
     * Update the ROAR task's game parameters.
     * This must be called after the startRun() method.
     *
     * @method
     * @async
     */
    updateTaskParams(newParams: {
        [key: string]: unknown;
    }): Promise<void>;
    /**
     * Add interaction data for the current trial
     *
     * This will keep a running log of interaction data for the current trial.
     * The log will be reset after each `writeTrial` call.
     
     * @param {InteractionEvent} interaction - interaction event
     * @method
     * @async
     */
    addInteraction(interaction: InteractionEvent): void;
    /**
     * Update the engagement flags for the current run.
     *
     * @param {string[]} flagNames - The names of the engagement flags to add.
     * @param {boolean} markAsReliable - Whether or not to mark the run as reliable, defaults to false
     * @method
     * @async
     *
     * Please note that calling this function with a new set of engagement flags will
     * overwrite the previous set.
     */
    updateEngagementFlags(flagNames: string[], markAsReliable?: boolean, reliableByBlock?: undefined): Promise<void>;
    /**
     * Finish the ROAR run by marking it as finished in Firestore.
     * Call this method after the jsPsych experiment finishes. For example:
     *
     * ```javascript
     * jsPsych.init({
     *   timeline: exp,
     *   on_finish: function(data) {
     *     firekit.finishRun();
     *   }
     * });
     * ```
     * @method
     * @async
     * @param {Object} [finishingMetaData={}] - Optional metadata to include when marking the run as complete.
     * @returns {Promise<boolean | undefined>} - Resolves when the run has been marked as complete.
     * @throws {Error} - Throws an error if the run has not been started yet.
     */
    finishRun(finishingMetaData?: {
        [key: string]: unknown;
    }): Promise<boolean | undefined>;
    /**
     * Abort the ROAR run, preventing any further writes to Firestore.
     * @method
     */
    abortRun(): void;
    /**
     * Add new trial data to this run on Firestore.
     *
     * ROAR expects certain data to be added to each trial:
     * - assessment_stage: string, either practice_response or test_response
     * - correct: boolean, whether the correct answer was correct
     * - subtask: string (optional), the name of the subtask
     * - thetaEstimate: number (optional), the ability estimate for adaptive assessments
     * - thetaSE: number (optional), the standard error of the ability estimate for adaptive assessments
     *
     * This method can be added to individual jsPsych trials by calling it from
     * the `on_finish` function, like so:
     *
     * ```javascript
     * var trial = {
     *   type: 'image-keyboard-response',
     *   stimulus: 'imgA.png',
     *   on_finish: function(data) {
     *     firekit.addTrialData(data);
     *   }
     * };
     * ```
     *
     * Or you can call it from all trials in a jsPsych
     * timeline by calling it from the `on_data_update` callback. In the latter
     * case, you can avoid saving extraneous trials by conditionally calling
     * this method based on the data. For example:
     *
     * ```javascript
     * const timeline = [
     *   // A fixation trial; don't save to Firestore
     *   {
     *     type: htmlKeyboardResponse,
     *     stimulus: '<div style="font-size:60px;">+</div>',
     *     choices: "NO_KEYS",
     *     trial_duration: 500,
     *   },
     *   // A stimulus and response trial; save to Firestore
     *   {
     *     type: imageKeyboardResponse,
     *     stimulus: 'imgA.png',
     *     data: { save: true },
     *   }
     * ]
     * jsPsych.init({
     *   timeline: timeline,
     *   on_data_update: function(data) {
     *     if (data.save) {
     *       firekit.addTrialData(data);
     *     }
     *   }
     * });
     * ```
     *
     * @method
     * @async
     * @param {*} trialData - An object containing trial data.
     */
    writeTrial(trialData: TrialData, computedScoreCallback?: (rawScores: RawScores) => Promise<ComputedScores>): Promise<void>;
    getStorageDownloadUrl(filePath: string): Promise<string>;
    /**
     * Generates a standardized file path for recordings.
     * @param {string} filename - The file name
     * @param {string} [assessmentPid] - Optional assessmentPid. Prioritizes assigned assessmentPid and defaults to assessmentUid
     * @returns Standardized file path for recordings
     */
    private generateFilePath;
    /**
     * Upload recordings to GCP using Firebase SDK.
     * The Firebase project and storage bucket are environment-specific.
     * Bucket format: "roar-assessment-recordings-{environment}".
     * @param {string} filename - The file name
     * @param {string} [assessmentPid] - Optional assessmentPid.
     * @param {File | Blob} fileOrBlob - The file or blob to upload
     * @param {Record<string, string>} [customMetadata] - Optional metadata to attach to the file (see SettableMetadata interface in Firebase docs)
     * @returns target storage url
     */
    uploadFileOrBlobToStorage({ filename, assessmentPid, fileOrBlob, customMetadata, }: {
        filename: string;
        assessmentPid?: string;
        fileOrBlob: File | Blob;
        customMetadata?: Record<string, string>;
    }): Promise<string>;
    /**
     * Processes the next pending upload if under the concurrency limit of 3.
     * Called after enqueuing a new upload and after each upload completes or fails.
     */
    private processUploadQueue;
}
export {};
