/**
 * WASM Helper for Hero Vault Extension
 * 
 * This module handles loading and initializing the WASM module,
 * and provides a typed interface to the WASM functions.
 */

// Import types for TypeScript
interface WasmModule {
  // Session management
  init_session: (keyspace: string, password: string) => Promise<void>;
  create_keyspace: (keyspace: string, password: string) => Promise<void>;
  lock_session: () => void;
  is_unlocked: () => boolean;
  
  // Keypair management
  add_keypair: (key_type: string | undefined, metadata: string | undefined) => Promise<string>;
  list_keypairs: () => Promise<string>;
  select_keypair: (key_id: string) => Promise<void>;
  current_keypair_metadata: () => Promise<any>;
  current_keypair_public_key: () => Promise<Uint8Array>;
  
  // Cryptographic operations
  sign: (message: Uint8Array) => Promise<string>;
  verify: (message: Uint8Array, signature: string) => Promise<boolean>;
  encrypt_data: (data: Uint8Array) => Promise<Uint8Array>;
  decrypt_data: (encrypted: Uint8Array) => Promise<Uint8Array>;
  
  // Rhai scripting
  init_rhai_env: () => void;
  run_rhai: (script: string) => Promise<string>;
}

// Global reference to the WASM module
let wasmModule: WasmModule | null = null;
let isInitializing = false;
let initPromise: Promise<void> | null = null;

/**
 * Initialize the WASM module
 * This should be called before any other WASM functions
 */
export const initWasm = async (): Promise<void> => {
  if (wasmModule) {
    return Promise.resolve(); // Already initialized
  }
  
  if (isInitializing && initPromise) {
    return initPromise; // Already initializing
  }
  
  isInitializing = true;
  
  initPromise = new Promise<void>(async (resolve, reject) => {
    try {
      try {
        // Import the WASM module
        // Use a relative path that will be resolved by Vite during build
        const wasmImport = await import('../../public/wasm/wasm_app.js');
        
        // Initialize the WASM module
        await wasmImport.default();
        
        // Store the WASM module globally
        wasmModule = wasmImport as unknown as WasmModule;
        
        console.log('WASM module initialized successfully');
        resolve();
      } catch (error) {
        console.error('Failed to initialize WASM module:', error);
        reject(error);
      }
      
    } finally {
      isInitializing = false;
    }
  });
  
  return initPromise;
};

/**
 * Get the WASM module
 * This will initialize the module if it hasn't been initialized yet
 */
export const getWasmModule = async (): Promise<WasmModule> => {
  if (!wasmModule) {
    await initWasm();
  }
  
  if (!wasmModule) {
    throw new Error('WASM module failed to initialize');
  }
  
  return wasmModule;
};

/**
 * Check if the WASM module is initialized
 */
export const isWasmInitialized = (): boolean => {
  return wasmModule !== null;
};

/**
 * Helper to convert string to Uint8Array
 */
export const stringToUint8Array = (str: string): Uint8Array => {
  const encoder = new TextEncoder();
  return encoder.encode(str);
};

/**
 * Helper to convert Uint8Array to string
 */
export const uint8ArrayToString = (array: Uint8Array): string => {
  const decoder = new TextDecoder();
  return decoder.decode(array);
};

/**
 * Helper to convert hex string to Uint8Array
 */
export const hexToUint8Array = (hex: string): Uint8Array => {
  const bytes = new Uint8Array(hex.length / 2);
  for (let i = 0; i < hex.length; i += 2) {
    bytes[i / 2] = parseInt(hex.substring(i, i + 2), 16);
  }
  return bytes;
};

/**
 * Helper to convert Uint8Array to hex string
 */
export const uint8ArrayToHex = (array: Uint8Array): string => {
  return Array.from(array)
    .map(b => b.toString(16).padStart(2, '0'))
    .join('');
};
