'use strict';

Object.defineProperty(exports, '__esModule', { value: true });

var buffer = require('buffer');
var mplCandyMachineCore = require('@metaplex-foundation/mpl-candy-machine-core');
var constants = require('../constants.cjs');
var CandyMachineHiddenSection = require('./CandyMachineHiddenSection.cjs');
var assert = require('../../../utils/assert.cjs');
var Model = require('../../../types/Model.cjs');
var Serializer = require('../../../types/Serializer.cjs');
var BigNumber = require('../../../types/BigNumber.cjs');
var Account = require('../../../types/Account.cjs');
var common = require('../../../utils/common.cjs');
var FeatureFlags = require('../../../types/FeatureFlags.cjs');

/**
 * This model contains all the relevant information about a Candy Machine.
 * This includes its settings but also all of the items (a.k.a. config lines)
 * loaded inside the Candy Machine along with some statistics about the items.
 *
 * @group Models
 */

/** @group Model Helpers */
const isCandyMachine = value => Model.isModel('candyMachine', value);

/** @group Model Helpers */
function assertCandyMachine(value) {
  Model.assertModel(isCandyMachine(value), `Expected CandyMachine model`);
}

/** @group Model Helpers */
const toCandyMachine = (account, candyGuard = null) => {
  const serializer = Serializer.createSerializerFromSolitaType(mplCandyMachineCore.CandyMachine, mplCandyMachineCore.candyMachineBeet.description);
  const parsedAccount = Serializer.deserializeAccount(account, serializer);
  const itemsAvailable = BigNumber.toBigNumber(parsedAccount.data.data.itemsAvailable);
  const itemsMinted = BigNumber.toBigNumber(parsedAccount.data.itemsRedeemed);
  const itemsRemaining = BigNumber.toBigNumber(itemsAvailable.sub(itemsMinted));
  let items = [];
  let itemsLoaded = 0;
  let isFullyLoaded = true;
  const {
    hiddenSettings
  } = parsedAccount.data.data;
  const {
    configLineSettings
  } = parsedAccount.data.data;
  let itemSettings;
  if (hiddenSettings) {
    itemSettings = {
      ...hiddenSettings,
      type: 'hidden'
    };
  } else {
    assert["default"](!!configLineSettings, 'Expected either hidden or config line settings');
    itemSettings = {
      ...configLineSettings,
      type: 'configLines'
    };
    const hiddenSection = CandyMachineHiddenSection.deserializeCandyMachineHiddenSection(account.data, itemsAvailable.toNumber(), itemsRemaining.toNumber(), itemSettings, constants.CANDY_MACHINE_HIDDEN_SECTION);
    items = hiddenSection.items;
    itemsLoaded = hiddenSection.itemsLoaded;
    isFullyLoaded = hiddenSection.itemsLoaded >= itemsAvailable.toNumber();
  }
  return {
    model: 'candyMachine',
    address: account.publicKey,
    accountInfo: Account.toAccountInfo(account),
    authorityAddress: parsedAccount.data.authority,
    mintAuthorityAddress: parsedAccount.data.mintAuthority,
    collectionMintAddress: parsedAccount.data.collectionMint,
    symbol: common.removeEmptyChars(parsedAccount.data.data.symbol),
    sellerFeeBasisPoints: parsedAccount.data.data.sellerFeeBasisPoints,
    isMutable: parsedAccount.data.data.isMutable,
    maxEditionSupply: BigNumber.toBigNumber(parsedAccount.data.data.maxSupply),
    creators: parsedAccount.data.data.creators.map(creator => ({
      ...creator,
      share: creator.percentageShare
    })),
    items,
    itemsAvailable,
    itemsMinted,
    itemsRemaining,
    itemsLoaded,
    isFullyLoaded,
    itemSettings,
    featureFlags: FeatureFlags.deserializeFeatureFlags(BigNumber.toBigNumber(parsedAccount.data.features).toArrayLike(buffer.Buffer, 'le', 8), 64)[0],
    candyGuard
  };
};
const toCandyMachineData = candyMachine => {
  return {
    itemsAvailable: candyMachine.itemsAvailable,
    symbol: candyMachine.symbol,
    sellerFeeBasisPoints: candyMachine.sellerFeeBasisPoints,
    maxSupply: candyMachine.maxEditionSupply,
    isMutable: candyMachine.isMutable,
    creators: candyMachine.creators.map(creator => ({
      ...creator,
      verified: false,
      percentageShare: creator.share
    })),
    configLineSettings: candyMachine.itemSettings.type === 'configLines' ? candyMachine.itemSettings : null,
    hiddenSettings: candyMachine.itemSettings.type === 'hidden' ? candyMachine.itemSettings : null
  };
};
const getCandyMachineSize = data => {
  if (data.hiddenSettings) {
    return constants.CANDY_MACHINE_HIDDEN_SECTION;
  }

  // This should not happen as the candy machine input type
  // ensures exactly on of them is provided.
  assert["default"](!!data.configLineSettings, 'No config line settings nor hidden settings were provided. ' + 'Please provide one of them.');
  const itemsAvailable = BigNumber.toBigNumber(data.itemsAvailable).toNumber();
  const configLineSize = data.configLineSettings.nameLength + data.configLineSettings.uriLength;
  return Math.ceil(constants.CANDY_MACHINE_HIDDEN_SECTION +
  // Number of currently items inserted.
  4 +
  // Config line data.
  itemsAvailable * configLineSize + (
  // Bit mask to keep track of which ConfigLines have been added.
  4 + Math.floor(itemsAvailable / 8) + 1) + (
  // Mint indices.
  4 + itemsAvailable * 4));
};

exports.assertCandyMachine = assertCandyMachine;
exports.getCandyMachineSize = getCandyMachineSize;
exports.isCandyMachine = isCandyMachine;
exports.toCandyMachine = toCandyMachine;
exports.toCandyMachineData = toCandyMachineData;
//# sourceMappingURL=CandyMachine.cjs.map
