var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
import { createDelegateAuctioneerInstruction, createUpdateAuctioneerInstruction, createUpdateAuctionHouseInstruction, } from '@metaplex-foundation/mpl-auction-house';
import isEqual from 'lodash.isequal';
import { AUCTIONEER_ALL_SCOPES } from '../constants';
import { TreasuryDestinationOwnerRequiredError } from '../errors';
import { assertAuctioneerAuctionHouse, } from '../models/AuctionHouse';
import { TransactionBuilder } from '../../../utils';
import { useOperation, } from '../../../types';
import { NoInstructionsToSendError } from '../../../errors';
// -----------------
// Operation
// -----------------
const Key = 'UpdateAuctionHouseOperation';
/**
 * Updates an existing Auction House.
 *
 * ```ts
 * await metaplex
 *   .autionHouse()
 *   .update({
 *     auctionHouse,
 *     canChangeSalePrice: true, // Updates the canChangeSalePrice only.
 *   };
 * ```
 *
 * @group Operations
 * @category Constructors
 */
export const updateAuctionHouseOperation = useOperation(Key);
/**
 * @group Operations
 * @category Handlers
 */
export const updateAuctionHouseOperationHandler = {
    handle(operation, metaplex, scope) {
        return __awaiter(this, void 0, void 0, function* () {
            const { auctionHouse, auctioneerAuthority } = operation.input;
            const builder = updateAuctionHouseBuilder(metaplex, operation.input, scope);
            if (builder.isEmpty()) {
                throw new NoInstructionsToSendError(Key);
            }
            const output = yield builder.sendAndConfirm(metaplex, scope.confirmOptions);
            const currentAuctioneerAuthority = auctionHouse.hasAuctioneer
                ? auctionHouse.auctioneer.authority
                : undefined;
            const updatedAuctionHouse = yield metaplex.auctionHouse().findByAddress({
                address: auctionHouse.address,
                auctioneerAuthority: auctioneerAuthority !== null && auctioneerAuthority !== void 0 ? auctioneerAuthority : currentAuctioneerAuthority,
            }, scope);
            return Object.assign(Object.assign({}, output), { auctionHouse: updatedAuctionHouse });
        });
    },
};
/**
 * Updates an existing Auction House.
 *
 * ```ts
 * const transactionBuilder = metaplex
 *   .auctionHouse()
 *   .builders()
 *   .updateAuctionHouse({ auctionHouse, canChangeSalePrice: true })
 * ```
 *
 * @group Transaction Builders
 * @category Constructors
 */
export const updateAuctionHouseBuilder = (metaplex, params, options = {}) => {
    var _a, _b, _c, _d, _e, _f, _g;
    const { programs, payer = metaplex.rpc().getDefaultFeePayer() } = options;
    const authority = (_a = params.authority) !== null && _a !== void 0 ? _a : metaplex.identity();
    const { auctionHouse } = params;
    let treasuryWithdrawalDestinationOwner;
    let treasuryWithdrawalDestination;
    if (auctionHouse.isNative) {
        treasuryWithdrawalDestinationOwner =
            (_b = params.treasuryWithdrawalDestinationOwner) !== null && _b !== void 0 ? _b : auctionHouse.treasuryWithdrawalDestinationAddress;
        treasuryWithdrawalDestination = treasuryWithdrawalDestinationOwner;
    }
    else if (params.treasuryWithdrawalDestinationOwner) {
        treasuryWithdrawalDestinationOwner =
            params.treasuryWithdrawalDestinationOwner;
        treasuryWithdrawalDestination = metaplex
            .tokens()
            .pdas()
            .associatedTokenAccount({
            mint: auctionHouse.treasuryMint.address,
            owner: treasuryWithdrawalDestinationOwner,
            programs,
        });
    }
    else {
        throw new TreasuryDestinationOwnerRequiredError();
    }
    const originalData = {
        authority: auctionHouse.authorityAddress,
        feeWithdrawalDestination: auctionHouse.feeWithdrawalDestinationAddress,
        treasuryWithdrawalDestination: auctionHouse.treasuryWithdrawalDestinationAddress,
        sellerFeeBasisPoints: auctionHouse.sellerFeeBasisPoints,
        requiresSignOff: auctionHouse.requiresSignOff,
        canChangeSalePrice: auctionHouse.canChangeSalePrice,
    };
    const updatedData = {
        authority: (_c = params.newAuthority) !== null && _c !== void 0 ? _c : originalData.authority,
        feeWithdrawalDestination: (_d = params.feeWithdrawalDestination) !== null && _d !== void 0 ? _d : originalData.feeWithdrawalDestination,
        treasuryWithdrawalDestination,
        sellerFeeBasisPoints: (_e = params.sellerFeeBasisPoints) !== null && _e !== void 0 ? _e : originalData.sellerFeeBasisPoints,
        requiresSignOff: (_f = params.requiresSignOff) !== null && _f !== void 0 ? _f : originalData.requiresSignOff,
        canChangeSalePrice: (_g = params.canChangeSalePrice) !== null && _g !== void 0 ? _g : originalData.canChangeSalePrice,
    };
    const shouldSendUpdateInstruction = !isEqual(originalData, updatedData);
    const shouldAddAuctioneerAuthority = !auctionHouse.hasAuctioneer && !!params.auctioneerAuthority;
    const shouldUpdateAuctioneerAuthority = auctionHouse.hasAuctioneer &&
        !!params.auctioneerAuthority &&
        !params.auctioneerAuthority.equals(auctionHouse.auctioneer.authority);
    const shouldUpdateAuctioneerScopes = auctionHouse.hasAuctioneer &&
        !!params.auctioneerScopes &&
        !isEqual(params.auctioneerScopes.sort(), auctionHouse.auctioneer.scopes.sort());
    const shouldDelegateAuctioneer = shouldAddAuctioneerAuthority || shouldUpdateAuctioneerAuthority;
    return (TransactionBuilder.make()
        .setFeePayer(payer)
        // Update the Auction House data.
        .when(shouldSendUpdateInstruction, (builder) => {
        var _a, _b, _c, _d;
        return builder.add({
            instruction: createUpdateAuctionHouseInstruction({
                treasuryMint: auctionHouse.treasuryMint.address,
                payer: payer.publicKey,
                authority: authority.publicKey,
                newAuthority: updatedData.authority,
                feeWithdrawalDestination: updatedData.feeWithdrawalDestination,
                treasuryWithdrawalDestination,
                treasuryWithdrawalDestinationOwner,
                auctionHouse: auctionHouse.address,
            }, {
                sellerFeeBasisPoints: (_a = params.sellerFeeBasisPoints) !== null && _a !== void 0 ? _a : null,
                requiresSignOff: (_b = params.requiresSignOff) !== null && _b !== void 0 ? _b : null,
                canChangeSalePrice: (_c = params.canChangeSalePrice) !== null && _c !== void 0 ? _c : null,
            }),
            signers: [payer, authority],
            key: (_d = params.instructionKey) !== null && _d !== void 0 ? _d : 'updateAuctionHouse',
        });
    })
        // Attach or update a new Auctioneer instance to the Auction House.
        .when(shouldDelegateAuctioneer, (builder) => {
        var _a, _b;
        const auctioneerAuthority = params.auctioneerAuthority;
        const defaultScopes = auctionHouse.hasAuctioneer
            ? auctionHouse.auctioneer.scopes
            : AUCTIONEER_ALL_SCOPES;
        return builder.add({
            instruction: createDelegateAuctioneerInstruction({
                auctionHouse: auctionHouse.address,
                authority: authority.publicKey,
                auctioneerAuthority,
                ahAuctioneerPda: metaplex.auctionHouse().pdas().auctioneer({
                    auctionHouse: auctionHouse.address,
                    auctioneerAuthority,
                    programs,
                }),
            }, { scopes: (_a = params.auctioneerScopes) !== null && _a !== void 0 ? _a : defaultScopes }),
            signers: [authority],
            key: (_b = params.delegateAuctioneerInstructionKey) !== null && _b !== void 0 ? _b : 'delegateAuctioneer',
        });
    })
        // Update the Auctioneer scopes of the Auction House.
        .when(shouldUpdateAuctioneerScopes, (builder) => {
        var _a, _b, _c;
        assertAuctioneerAuctionHouse(auctionHouse);
        const auctioneerAuthority = (_a = params.auctioneerAuthority) !== null && _a !== void 0 ? _a : auctionHouse.auctioneer.authority;
        return builder.add({
            instruction: createUpdateAuctioneerInstruction({
                auctionHouse: auctionHouse.address,
                authority: authority.publicKey,
                auctioneerAuthority,
                ahAuctioneerPda: metaplex.auctionHouse().pdas().auctioneer({
                    auctionHouse: auctionHouse.address,
                    auctioneerAuthority,
                    programs,
                }),
            }, {
                scopes: (_b = params.auctioneerScopes) !== null && _b !== void 0 ? _b : auctionHouse.auctioneer.scopes,
            }),
            signers: [authority],
            key: (_c = params.updateAuctioneerInstructionKey) !== null && _c !== void 0 ? _c : 'updateAuctioneer',
        });
    }));
};
//# sourceMappingURL=updateAuctionHouse.js.map