/**
 * 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 {
  combineCodec,
  getDiscriminatedUnionDecoder,
  getDiscriminatedUnionEncoder,
  getStructDecoder,
  getStructEncoder,
  getTupleDecoder,
  getTupleEncoder,
  getU64Decoder,
  getU64Encoder,
  type Codec,
  type Decoder,
  type Encoder,
  type GetDiscriminatedUnionVariant,
  type GetDiscriminatedUnionVariantContent,
} from '@solana/kit';

/**
 * Enforces rules on the amount of tokens being transferred.
 * The rules can be above, below, equal to, or within a range.
 */

export type TransferAmountRule =
  | { __kind: 'Above'; fields: readonly [bigint] }
  | { __kind: 'Below'; fields: readonly [bigint] }
  | { __kind: 'Equal'; fields: readonly [bigint] }
  | { __kind: 'Rang'; fields: readonly [bigint, bigint] };

export type TransferAmountRuleArgs =
  | { __kind: 'Above'; fields: readonly [number | bigint] }
  | { __kind: 'Below'; fields: readonly [number | bigint] }
  | { __kind: 'Equal'; fields: readonly [number | bigint] }
  | { __kind: 'Rang'; fields: readonly [number | bigint, number | bigint] };

export function getTransferAmountRuleEncoder(): Encoder<TransferAmountRuleArgs> {
  return getDiscriminatedUnionEncoder([
    [
      'Above',
      getStructEncoder([['fields', getTupleEncoder([getU64Encoder()])]]),
    ],
    [
      'Below',
      getStructEncoder([['fields', getTupleEncoder([getU64Encoder()])]]),
    ],
    [
      'Equal',
      getStructEncoder([['fields', getTupleEncoder([getU64Encoder()])]]),
    ],
    [
      'Rang',
      getStructEncoder([
        ['fields', getTupleEncoder([getU64Encoder(), getU64Encoder()])],
      ]),
    ],
  ]);
}

export function getTransferAmountRuleDecoder(): Decoder<TransferAmountRule> {
  return getDiscriminatedUnionDecoder([
    [
      'Above',
      getStructDecoder([['fields', getTupleDecoder([getU64Decoder()])]]),
    ],
    [
      'Below',
      getStructDecoder([['fields', getTupleDecoder([getU64Decoder()])]]),
    ],
    [
      'Equal',
      getStructDecoder([['fields', getTupleDecoder([getU64Decoder()])]]),
    ],
    [
      'Rang',
      getStructDecoder([
        ['fields', getTupleDecoder([getU64Decoder(), getU64Decoder()])],
      ]),
    ],
  ]);
}

export function getTransferAmountRuleCodec(): Codec<
  TransferAmountRuleArgs,
  TransferAmountRule
> {
  return combineCodec(
    getTransferAmountRuleEncoder(),
    getTransferAmountRuleDecoder()
  );
}

// Data Enum Helpers.
export function transferAmountRule(
  kind: 'Above',
  data: GetDiscriminatedUnionVariantContent<
    TransferAmountRuleArgs,
    '__kind',
    'Above'
  >['fields']
): GetDiscriminatedUnionVariant<TransferAmountRuleArgs, '__kind', 'Above'>;
export function transferAmountRule(
  kind: 'Below',
  data: GetDiscriminatedUnionVariantContent<
    TransferAmountRuleArgs,
    '__kind',
    'Below'
  >['fields']
): GetDiscriminatedUnionVariant<TransferAmountRuleArgs, '__kind', 'Below'>;
export function transferAmountRule(
  kind: 'Equal',
  data: GetDiscriminatedUnionVariantContent<
    TransferAmountRuleArgs,
    '__kind',
    'Equal'
  >['fields']
): GetDiscriminatedUnionVariant<TransferAmountRuleArgs, '__kind', 'Equal'>;
export function transferAmountRule(
  kind: 'Rang',
  data: GetDiscriminatedUnionVariantContent<
    TransferAmountRuleArgs,
    '__kind',
    'Rang'
  >['fields']
): GetDiscriminatedUnionVariant<TransferAmountRuleArgs, '__kind', 'Rang'>;
export function transferAmountRule<
  K extends TransferAmountRuleArgs['__kind'],
  Data,
>(kind: K, data?: Data) {
  return Array.isArray(data)
    ? { __kind: kind, fields: data }
    : { __kind: kind, ...(data ?? {}) };
}

export function isTransferAmountRule<K extends TransferAmountRule['__kind']>(
  kind: K,
  value: TransferAmountRule
): value is TransferAmountRule & { __kind: K } {
  return value.__kind === kind;
}
