/**
 * This code was AUTOGENERATED using the Codama library.
 * Please DO NOT EDIT THIS FILE, instead use visitors
 * to add features, then rerun Codama to update it.
 *
 * @see https://github.com/codama-idl/codama
 */

import {
  assertIsInstructionWithAccounts,
  containsBytes,
  extendClient,
  getU8Encoder,
  SOLANA_ERROR__PROGRAM_CLIENTS__FAILED_TO_IDENTIFY_INSTRUCTION,
  SOLANA_ERROR__PROGRAM_CLIENTS__UNRECOGNIZED_INSTRUCTION_TYPE,
  SolanaError,
  type Address,
  type ClientWithTransactionPlanning,
  type ClientWithTransactionSending,
  type ExtendedClient,
  type Instruction,
  type InstructionWithData,
  type ReadonlyUint8Array,
} from "@solana/kit";
import {
  addSelfPlanAndSendFunctions,
  type SelfPlanAndSendFunctions,
} from "@solana/kit/program-client-core";
import {
  getWithdrawFundsInstructionAsync,
  parseWithdrawFundsInstruction,
  type ParsedWithdrawFundsInstruction,
  type WithdrawFundsAsyncInput,
} from "../instructions";

export const PRIVATE_CHANNEL_WITHDRAW_PROGRAM_PROGRAM_ADDRESS =
  "J231K9UEpS4y4KAPwGc4gsMNCjKFRMYcQBcjVW7vBhVi" as Address<"J231K9UEpS4y4KAPwGc4gsMNCjKFRMYcQBcjVW7vBhVi">;

export enum PrivateChannelWithdrawProgramInstruction {
  WithdrawFunds,
}

export function identifyPrivateChannelWithdrawProgramInstruction(
  instruction: { data: ReadonlyUint8Array } | ReadonlyUint8Array,
): PrivateChannelWithdrawProgramInstruction {
  const data = "data" in instruction ? instruction.data : instruction;
  if (containsBytes(data, getU8Encoder().encode(0), 0)) {
    return PrivateChannelWithdrawProgramInstruction.WithdrawFunds;
  }
  throw new SolanaError(
    SOLANA_ERROR__PROGRAM_CLIENTS__FAILED_TO_IDENTIFY_INSTRUCTION,
    { instructionData: data, programName: "privateChannelWithdrawProgram" },
  );
}

export type ParsedPrivateChannelWithdrawProgramInstruction<
  TProgram extends string = "J231K9UEpS4y4KAPwGc4gsMNCjKFRMYcQBcjVW7vBhVi",
> = {
  instructionType: PrivateChannelWithdrawProgramInstruction.WithdrawFunds;
} & ParsedWithdrawFundsInstruction<TProgram>;

export function parsePrivateChannelWithdrawProgramInstruction<
  TProgram extends string,
>(
  instruction: Instruction<TProgram> & InstructionWithData<ReadonlyUint8Array>,
): ParsedPrivateChannelWithdrawProgramInstruction<TProgram> {
  const instructionType =
    identifyPrivateChannelWithdrawProgramInstruction(instruction);
  switch (instructionType) {
    case PrivateChannelWithdrawProgramInstruction.WithdrawFunds: {
      assertIsInstructionWithAccounts(instruction);
      return {
        instructionType: PrivateChannelWithdrawProgramInstruction.WithdrawFunds,
        ...parseWithdrawFundsInstruction(instruction),
      };
    }
    default:
      throw new SolanaError(
        SOLANA_ERROR__PROGRAM_CLIENTS__UNRECOGNIZED_INSTRUCTION_TYPE,
        {
          instructionType: instructionType as string,
          programName: "privateChannelWithdrawProgram",
        },
      );
  }
}

export type PrivateChannelWithdrawProgramPlugin = {
  instructions: PrivateChannelWithdrawProgramPluginInstructions;
  identifyInstruction: typeof identifyPrivateChannelWithdrawProgramInstruction;
  parseInstruction: typeof parsePrivateChannelWithdrawProgramInstruction;
};

export type PrivateChannelWithdrawProgramPluginInstructions = {
  withdrawFunds: (
    input: WithdrawFundsAsyncInput,
  ) => ReturnType<typeof getWithdrawFundsInstructionAsync> &
    SelfPlanAndSendFunctions;
};

export type PrivateChannelWithdrawProgramPluginRequirements =
  ClientWithTransactionPlanning & ClientWithTransactionSending;

export function privateChannelWithdrawProgramProgram() {
  return <T extends PrivateChannelWithdrawProgramPluginRequirements>(
    client: T,
  ): ExtendedClient<
    T,
    { privateChannelWithdrawProgram: PrivateChannelWithdrawProgramPlugin }
  > => {
    return extendClient(client, {
      privateChannelWithdrawProgram: <PrivateChannelWithdrawProgramPlugin>{
        instructions: {
          withdrawFunds: (input) =>
            addSelfPlanAndSendFunctions(
              client,
              getWithdrawFundsInstructionAsync(input),
            ),
        },
        identifyInstruction: identifyPrivateChannelWithdrawProgramInstruction,
        parseInstruction: parsePrivateChannelWithdrawProgramInstruction,
      },
    });
  };
}
