"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.driveChangesOperation = driveChangesOperation;
exports.driveConnectionOperation = driveConnectionOperation;
exports.driveOperation = driveOperation;
exports.driveStatsOperation = driveStatsOperation;
exports.driveVoidOperation = driveVoidOperation;
var _types = require("../types");
var _ioProcessor = require("./ioProcessor");
/**
 * Async Operation Driver
 *
 * Drives async operations returned by sync SDK-KIT methods.
 * This is where ALL the async logic lives - the C++ layer is just a thin bridge.
 *
 * Key responsibilities:
 * - Call resume() in a loop until DONE
 * - When IO is needed, process all pending IO items
 * - Extract and return the final result
 */

/**
 * Drive an async operation to completion
 *
 * @param operation - The native operation to drive
 * @param database - The native sync database (for IO queue access)
 * @param context - IO context with auth and URL information
 * @returns Promise that resolves when operation completes
 */
async function driveOperation(operation, database, context) {
  while (true) {
    // Resume the operation
    const status = operation.resume();

    // Operation completed successfully
    if (status === _types.TursoStatus.DONE) {
      // Extract and return the result based on result type
      const resultKind = operation.resultKind();
      switch (resultKind) {
        case _types.SyncOperationResultType.NONE:
          return undefined;
        case _types.SyncOperationResultType.CONNECTION:
          return operation.extractConnection();
        case _types.SyncOperationResultType.CHANGES:
          return operation.extractChanges();
        case _types.SyncOperationResultType.STATS:
          return operation.extractStats();
        default:
          throw new Error(`Unknown result type: ${resultKind}`);
      }
    }

    // Operation needs IO
    if (status === _types.TursoStatus.IO) {
      // Process all pending IO items
      await processIoQueue(database, context);

      // Step callbacks after IO processing
      database.ioStepCallbacks();

      // Continue resume loop
      continue;
    }

    // Any other status is an error
    throw new Error(`Unexpected status from operation.resume(): ${status}`);
  }
}

/**
 * Process all pending IO items in the queue
 *
 * @param database - The native sync database
 * @param context - IO context with auth and URL information
 */
async function processIoQueue(database, context) {
  const promises = [];

  // Take all available IO items from the queue
  while (true) {
    const ioItem = database.ioTakeItem();
    if (!ioItem) {
      break; // No more items
    }

    // Process each item (potentially in parallel)
    promises.push((0, _ioProcessor.processIoItem)(ioItem, context));
  }

  // Wait for all IO operations to complete
  await Promise.all(promises);
}

/**
 * Helper type for operations that return connections
 */
async function driveConnectionOperation(operation, database, context) {
  return driveOperation(operation, database, context);
}

/**
 * Helper type for operations that return changes
 */
async function driveChangesOperation(operation, database, context) {
  return driveOperation(operation, database, context);
}

/**
 * Helper type for operations that return stats
 */
async function driveStatsOperation(operation, database, context) {
  return driveOperation(operation, database, context);
}

/**
 * Helper type for operations that return void
 */
async function driveVoidOperation(operation, database, context) {
  return driveOperation(operation, database, context);
}
//# sourceMappingURL=asyncOperation.js.map