import { EndSettingType } from '@metaplex-solarti/mpl-candy-machine';
import { countCandyMachineV2Items, parseCandyMachineV2Items, getCandyMachineV2UuidFromAddress } from '../helpers.mjs';
import { CandyMachineV2Program } from '../program.mjs';
import assert from '../../../utils/assert.mjs';
import { amount, SOL, lamports } from '../../../types/Amount.mjs';
import { toBigNumber } from '../../../types/BigNumber.mjs';
import { removeEmptyChars } from '../../../utils/common.mjs';
import { toOptionDateTime, toDateTime } from '../../../types/DateTime.mjs';

// -----------------
// Program to Model
// -----------------

/** @group Model Helpers */
const isCandyMachineV2 = value => typeof value === 'object' && value.model === 'candyMachineV2';

/** @group Model Helpers */
function assertCandyMachineV2(value) {
  assert(isCandyMachineV2(value), 'Expected CandyMachineV2 type');
}

/** @group Model Helpers */
const toCandyMachineV2 = (account, unparsedAccount, collectionAccount, mint) => {
  assert(mint === null || account.data.tokenMint !== null && mint.address.equals(account.data.tokenMint));
  const itemsAvailable = toBigNumber(account.data.data.itemsAvailable);
  const itemsMinted = toBigNumber(account.data.itemsRedeemed);
  const {
    endSettings
  } = account.data.data;
  const {
    hiddenSettings
  } = account.data.data;
  const {
    whitelistMintSettings
  } = account.data.data;
  const {
    gatekeeper
  } = account.data.data;
  const rawData = unparsedAccount.data;
  const itemsLoaded = hiddenSettings ? toBigNumber(0) : countCandyMachineV2Items(rawData);
  const items = hiddenSettings ? [] : parseCandyMachineV2Items(rawData);
  return {
    model: 'candyMachineV2',
    address: account.publicKey,
    programAddress: account.owner,
    version: account.owner.equals(CandyMachineV2Program.publicKey) ? 2 : 1,
    authorityAddress: account.data.authority,
    walletAddress: account.data.wallet,
    tokenMintAddress: account.data.tokenMint,
    collectionMintAddress: collectionAccount && collectionAccount.exists ? collectionAccount.data.mint : null,
    uuid: account.data.data.uuid,
    price: amount(account.data.data.price, mint ? mint.currency : SOL),
    symbol: removeEmptyChars(account.data.data.symbol),
    sellerFeeBasisPoints: account.data.data.sellerFeeBasisPoints,
    isMutable: account.data.data.isMutable,
    retainAuthority: account.data.data.retainAuthority,
    goLiveDate: toOptionDateTime(account.data.data.goLiveDate),
    maxEditionSupply: toBigNumber(account.data.data.maxSupply),
    items,
    itemsAvailable,
    itemsMinted,
    itemsRemaining: toBigNumber(itemsAvailable.sub(itemsMinted)),
    itemsLoaded,
    isFullyLoaded: itemsAvailable.lte(itemsLoaded),
    // eslint-disable-next-line no-nested-ternary
    endSettings: endSettings ? endSettings.endSettingType === EndSettingType.Date ? {
      endSettingType: EndSettingType.Date,
      date: toDateTime(endSettings.number)
    } : {
      endSettingType: EndSettingType.Amount,
      number: toBigNumber(endSettings.number)
    } : null,
    hiddenSettings,
    whitelistMintSettings: whitelistMintSettings ? {
      ...whitelistMintSettings,
      discountPrice: whitelistMintSettings.discountPrice ? lamports(whitelistMintSettings.discountPrice) : null
    } : null,
    gatekeeper: gatekeeper ? {
      ...gatekeeper,
      network: gatekeeper.gatekeeperNetwork
    } : null,
    creators: account.data.data.creators
  };
};

// -----------------
// Model to Configs
// -----------------

/**
 * This object provides a common interface for the configurations required
 * to create or update Candy Machines.
 *
 * @group Models
 */

/** @group Model Helpers */
const toCandyMachineV2Configs = candyMachine => {
  return {
    wallet: candyMachine.walletAddress,
    tokenMint: candyMachine.tokenMintAddress,
    ...candyMachine
  };
};

// -----------------
// Configs to Program
// -----------------

/** @group Models */

/** @group Model Helpers */
const toCandyMachineV2InstructionData = (address, configs) => {
  const {
    endSettings
  } = configs;
  const {
    whitelistMintSettings
  } = configs;
  const {
    gatekeeper
  } = configs;
  return {
    wallet: configs.wallet,
    tokenMint: configs.tokenMint,
    data: {
      ...configs,
      uuid: getCandyMachineV2UuidFromAddress(address),
      price: configs.price.basisPoints,
      maxSupply: configs.maxEditionSupply,
      endSettings: endSettings ? {
        ...endSettings,
        number: endSettings.endSettingType === EndSettingType.Date ? endSettings.date : endSettings.number
      } : null,
      whitelistMintSettings: whitelistMintSettings ? {
        ...whitelistMintSettings,
        discountPrice: whitelistMintSettings.discountPrice?.basisPoints ?? null
      } : null,
      gatekeeper: gatekeeper ? {
        ...gatekeeper,
        gatekeeperNetwork: gatekeeper.network
      } : null
    }
  };
};

export { assertCandyMachineV2, isCandyMachineV2, toCandyMachineV2, toCandyMachineV2Configs, toCandyMachineV2InstructionData };
//# sourceMappingURL=CandyMachineV2.mjs.map
