import ZkExpoModule from "./ZkExpoModule";

export async function groth16Prove(
  wasm_path: string,
  zkey_path: string,
  inputs: string,
): Promise<{ proof: any; publicSignals: any }> {
  try {
    if (wasm_path.startsWith("file://"))
      wasm_path = wasm_path.replace("file://", "");
    if (zkey_path.startsWith("file://"))
      zkey_path = zkey_path.replace("file://", "");
    let res = await ZkExpoModule.groth16Prove(wasm_path, zkey_path, inputs);
    let { proof, public_signals } = JSON.parse(res);
    return { proof, publicSignals: public_signals };
  } catch (e) {
    console.error("ZkExpoModule Error", e);
    throw new Error(`ZkExpoModule Error: ${e}`);
  }
}

export async function groth16ProveV2(
  graph_path: string,
  zkey_path: string,
  inputs: string,
): Promise<{ proof: any; publicSignals: any }> {
  try {
    if (graph_path.startsWith("file://"))
      graph_path = graph_path.replace("file://", "");
    if (zkey_path.startsWith("file://"))
      zkey_path = zkey_path.replace("file://", "");
    let res = await ZkExpoModule.groth16ProveV2(graph_path, zkey_path, inputs);
    let { proof, public_signals } = JSON.parse(res);
    return { proof, publicSignals: public_signals };
  } catch (e) {
    console.error("ZkExpoModule Error", e);
    throw new Error(`ZkExpoModule Error: ${e}`);
  }
}

export async function halo2Prove(
  wasmPath: string,
  publicInputs: number[],
): Promise<string> {
  try {
    if (wasmPath.startsWith("file://"))
      wasmPath = wasmPath.replace("file://", "");
    let res = await ZkExpoModule.halo2Prove(
      wasmPath,
      JSON.stringify(publicInputs),
    );
    return res;
  } catch (e) {
    console.error("ZkExpoModule:halo2Prove Error", e);
    throw new Error(`ZkExpoModule:halo2Prove Error: ${e}`);
  }
}

export async function noirProve(
  dataPath: string,
  witnessJson: string,
  type: "scheme" | "bytecodeJson" = "bytecodeJson"
): Promise<{ success: true; proof: string; vk: string } | { success: false }> {
  try {
    if (dataPath.startsWith("file://")) dataPath = dataPath.replace("file://", "");
    const res = await ZkExpoModule.noirProve(
      dataPath,
      witnessJson,
      type
    );
    console.log(res);
    return JSON.parse(res);
  } catch (e) {
    console.error("ZkExpoModule Error", e);
    throw new Error(`ZkExpoModule Error: ${e}`);
  }
}

export async function addToCache(
  functionName: "groth16_prove_v2" = "groth16_prove_v2",
  path1: string,
  path2: string,
): Promise<void> {
  try {
    if (path1.startsWith("file://")) path1 = path1.replace("file://", "");
    if (path2.startsWith("file://")) path2 = path2.replace("file://", "");
    await ZkExpoModule.addToCache(
      functionName,
      path1,
      path2
    );

  } catch (e) {
    console.error("ZkExpoModule Error", e);
    throw new Error(`ZkExpoModule Error: ${e}`);
  }
}

export async function clearCache(): Promise<void> {
  try {
    await ZkExpoModule.clearCache();

  } catch (e) {
    console.error("ZkExpoModule Error", e);
    throw new Error(`ZkExpoModule Error: ${e}`);
  }
}
