import { BaseCoreSDK } from "./../mixins/base-core-sdk";
import * as accounts from ".";
import * as erc721 from "../erc721";
import { AuthTokenType } from "@bosonprotocol/common";
import { BigNumber } from "@ethersproject/bignumber";
import { AddressZero } from "@ethersproject/constants";
import { orchestration } from "..";
import { getValueFromLogs, getValuesFromLogsExt } from "../utils/logs";
export class AccountsMixin extends BaseCoreSDK {
    /* -------------------------------------------------------------------------- */
    /*                           Account related methods                          */
    /* -------------------------------------------------------------------------- */
    /* --------------------------------- Seller --------------------------------- */
    /**
     * Returns seller entity from subgraph.
     * @param sellerId - ID of seller entity to query for.
     * @param queryVars - Optional query variables to skip, order or filter.
     * @returns Seller entity from subgraph.
     */
    async getSellerById(sellerId, queryVars) {
        return accounts.subgraph.getSellerById(this._subgraphUrl, sellerId, queryVars);
    }
    /**
     * Returns seller entity from subgraph.
     * @param assistant - Assistant address of seller entity to query for.
     * @param queryVars - Optional query variables to skip, order or filter.
     * @returns Seller entity from subgraph.
     */
    async getSellerByAssistant(assistant, queryVars) {
        return accounts.subgraph.getSellerByAssistant(this._subgraphUrl, assistant, queryVars);
    }
    /**
     * Returns seller entity from subgraph.
     * @param admin - Admin address of seller entity to query for.
     * @param queryVars - Optional query variables to skip, order or filter.
     * @returns Seller entity from subgraph.
     */
    async getSellerByAdmin(admin, queryVars) {
        return accounts.subgraph.getSellerByAdmin(this._subgraphUrl, admin, queryVars);
    }
    /**
     * Returns seller entities from subgraph.
     * @param treasury - Treasury address of seller entities to query for.
     * @param queryVars - Optional query variables to skip, order or filter.
     * @returns Seller entities from subgraph.
     */
    async getSellersByTreasury(treasury, queryVars) {
        return accounts.subgraph.getSellersByTreasury(this._subgraphUrl, treasury, queryVars);
    }
    /**
     * Returns seller entity from subgraph. Matches `assistant`, `clerk`, `admin` or `treasury`.
     * @param address - Address of seller entity to query for.
     * @param queryVars - Optional query variables to skip, order or filter.
     * @returns Seller entity from subgraph.
     */
    async getSellersByAddress(address, queryVars) {
        if (address === AddressZero) {
            throw new Error(`Unsupported search address '${AddressZero}'`);
        }
        let seller = await accounts.subgraph.getSellerByAddress(this._subgraphUrl, address, queryVars);
        if (!seller && this._lens?.LENS_HUB_CONTRACT) {
            // If seller is not found per address, try to find per authToken
            const tokenType = AuthTokenType.LENS; // only LENS for now
            const sellerId = await this.searchSellerFromAuthToken(address, tokenType);
            seller = sellerId
                ? await accounts.subgraph.getSellerById(this._subgraphUrl, sellerId, queryVars)
                : null;
        }
        return [seller].filter((seller) => !!seller);
    }
    /**
     * Returns the seller id found in the subgraph, if any, based on an authTokenId owned by the specified address
     * @param address - Address of seller entity to query for.
     * @param tokenType - type of authToken to look for.
     * @returns sellerId if found
     */
    async searchSellerFromAuthToken(address, tokenType) {
        if (tokenType !== AuthTokenType.LENS) {
            // only LENS for now
            throw new Error(`Unsupported authTokenType '${tokenType}'`);
        }
        if (!this._lens || !this._lens?.LENS_HUB_CONTRACT) {
            throw new Error("LENS contract is not configured in Core-SDK");
        }
        const balance = await erc721.handler.balanceOf({
            contractAddress: this._lens?.LENS_HUB_CONTRACT,
            owner: address,
            web3Lib: this._web3Lib
        });
        const balanceBN = BigNumber.from(balance);
        // If balanceBN is > 0, fetch all LENS authTokenId from the subgraph and check owner for each of them
        if (balanceBN.gt(0)) {
            const authTokenIdSellers = await accounts.subgraph.getAuthTokenIds(this._subgraphUrl, {
                authTokenType: AuthTokenType.LENS
            });
            for (const seller of authTokenIdSellers) {
                const owner = await erc721.handler.ownerOf({
                    contractAddress: this._lens?.LENS_HUB_CONTRACT,
                    tokenId: seller.authTokenId,
                    web3Lib: this._web3Lib
                });
                if (owner.toLowerCase() === address.toLowerCase()) {
                    return seller.id;
                }
            }
        }
        return;
    }
    /**
     * Returns seller entity from subgraph that owns the given auth token (if any).
     * @param tokenId - tokenId of the Auth Token.
     * @param tokenType - Type of the Auth Token (1 for LENS, ...).
     * @param queryVars - Optional query variables to skip, order or filter.
     * @returns Seller entity from subgraph.
     */
    async getSellerByAuthToken(tokenId, tokenType, queryVars) {
        if (tokenType !== AuthTokenType.LENS) {
            // only LENS for now
            throw new Error(`Unsupported authTokenType '${tokenType}'`);
        }
        return accounts.subgraph.getSellerByAuthToken(this._subgraphUrl, tokenId, tokenType, queryVars);
    }
    /**
     * Returns seller entities from subgraph.
     * @param queryVars - Optional query variables to skip, order or filter.
     * @returns Seller entities from subgraph.
     */
    async getSellers(queryVars) {
        return accounts.subgraph.getSellers(this._subgraphUrl, queryVars);
    }
    // Implementation
    async createSeller(sellerToCreate, overrides = {}) {
        const { returnTxInfo } = overrides;
        const sellerArgs = {
            sellerToCreate,
            web3Lib: this._web3Lib,
            theGraphStorage: this._theGraphStorage,
            metadataStorage: this._metadataStorage,
            contractAddress: overrides.contractAddress || this._protocolDiamond
        };
        if (returnTxInfo === true) {
            return accounts.handler.createSeller({
                ...sellerArgs,
                returnTxInfo: true
            });
        }
        else {
            return accounts.handler.createSeller({
                ...sellerArgs,
                returnTxInfo: false
            });
        }
    }
    // Implementation
    async createSellerAndOffer(sellerToCreate, offerToCreate, overrides = {}) {
        const { returnTxInfo } = overrides;
        const orchestrationArgs = {
            sellerToCreate,
            offerToCreate,
            web3Lib: this._web3Lib,
            theGraphStorage: this._theGraphStorage,
            metadataStorage: this._metadataStorage,
            contractAddress: overrides.contractAddress || this._protocolDiamond
        };
        if (returnTxInfo === true) {
            return orchestration.handler.createOfferAndSeller({
                ...orchestrationArgs,
                returnTxInfo: true
            });
        }
        else {
            return orchestration.handler.createOfferAndSeller({
                ...orchestrationArgs,
                returnTxInfo: false
            });
        }
    }
    // Implementation
    async updateSeller(sellerUpdates, overrides = {}) {
        const { returnTxInfo } = overrides;
        const sellerArgs = {
            sellerUpdates,
            web3Lib: this._web3Lib,
            theGraphStorage: this._theGraphStorage,
            metadataStorage: this._metadataStorage,
            contractAddress: overrides.contractAddress || this._protocolDiamond
        };
        if (returnTxInfo === true) {
            return accounts.handler.updateSeller({
                ...sellerArgs,
                returnTxInfo: true
            });
        }
        else {
            return accounts.handler.updateSeller({
                ...sellerArgs,
                returnTxInfo: false
            });
        }
    }
    // Implementation
    async optInToSellerUpdate(sellerUpdates, overrides = {}) {
        const { returnTxInfo } = overrides;
        const sellerArgs = {
            sellerUpdates,
            web3Lib: this._web3Lib,
            contractAddress: overrides.contractAddress || this._protocolDiamond
        };
        if (returnTxInfo === true) {
            return accounts.handler.optInToSellerUpdate({
                ...sellerArgs,
                returnTxInfo: true
            });
        }
        else {
            return accounts.handler.optInToSellerUpdate({
                ...sellerArgs,
                returnTxInfo: false
            });
        }
    }
    /**
     * Updates seller account by calling the `AccountHandlerFacet` contract,
     * then optIn for all updates doable by the same account. Only callable
     * by admin.
     * @param sellerUpdates - Values to update.
     * @param overrides - Optional overrides.
     * @returns Transaction response.
     */
    async updateSellerAndOptIn(sellerUpdates, overrides = {}) {
        const updateTx = await this.updateSeller(sellerUpdates, {
            ...overrides,
            returnTxInfo: false
        });
        const txReceipt = await updateTx.wait();
        const pendingSellerUpdate = this.getPendingSellerUpdateFromLogs(txReceipt.logs);
        // Find all updates that can be opted in by the current account
        const currentAccount = (await this._web3Lib.getSignerAddress()).toLowerCase();
        const fieldsToUpdate = {
            assistant: currentAccount === pendingSellerUpdate.assistant?.toLowerCase(),
            admin: currentAccount === pendingSellerUpdate.admin?.toLowerCase(),
            authToken: pendingSellerUpdate.tokenType !== undefined &&
                pendingSellerUpdate.tokenType !== null &&
                pendingSellerUpdate.tokenType !== AuthTokenType.NONE
        };
        if (fieldsToUpdate.assistant ||
            fieldsToUpdate.admin ||
            fieldsToUpdate.authToken) {
            return this.optInToSellerUpdate({
                id: sellerUpdates.id,
                fieldsToUpdate: {
                    assistant: currentAccount === pendingSellerUpdate.assistant.toLowerCase(),
                    admin: currentAccount === pendingSellerUpdate.admin.toLowerCase(),
                    authToken: pendingSellerUpdate.tokenType !== AuthTokenType.NONE
                }
            });
        }
        // If there is nothing to optIn from the current account, then return the response from updateSeller
        return updateTx;
    }
    /* ---------------------------------- Buyer --------------------------------- */
    /**
     * Returns buyer entity from subgraph.
     * @param buyerId - ID of buyer entity to query for.
     * @param queryVars - Optional query variables to skip, order or filter.
     * @returns Buyer entity from subgraph.
     */
    async getBuyerById(buyerId, queryVars) {
        return accounts.subgraph.getBuyerById(this._subgraphUrl, buyerId, queryVars);
    }
    /**
     * Returns buyer entities from subgraph.
     * @param queryVars - Optional query variables to skip, order or filter.
     * @returns Buyer entities from subgraph.
     */
    async getBuyers(queryVars) {
        return accounts.subgraph.getBuyers(this._subgraphUrl, queryVars);
    }
    // Implementation
    async createBuyer(buyerToCreate, overrides = {}) {
        const { returnTxInfo } = overrides;
        const buyerArgs = {
            buyerToCreate,
            web3Lib: this._web3Lib,
            theGraphStorage: this._theGraphStorage,
            metadataStorage: this._metadataStorage,
            contractAddress: overrides.contractAddress || this._protocolDiamond
        };
        if (returnTxInfo === true) {
            return accounts.handler.createBuyer({
                ...buyerArgs,
                returnTxInfo: true
            });
        }
        else {
            return accounts.handler.createBuyer({
                ...buyerArgs,
                returnTxInfo: false
            });
        }
    }
    // Implementation
    async createDisputeResolver(disputeResolverToCreate, overrides = {}) {
        const { returnTxInfo } = overrides;
        const disputeArgs = {
            disputeResolverToCreate,
            contractAddress: overrides.contractAddress || this._protocolDiamond,
            web3Lib: this._web3Lib
        };
        if (returnTxInfo === true) {
            return accounts.handler.createDisputeResolver({
                ...disputeArgs,
                returnTxInfo: true
            });
        }
        else {
            return accounts.handler.createDisputeResolver({
                ...disputeArgs,
                returnTxInfo: false
            });
        }
    }
    /**
     * Utility method to retrieve the created `exchangeId` from logs after calling `commitToOffer`.
     * @param logs - Logs to search in.
     * @returns Created exchange id.
     */
    getDisputeResolverIdFromLogs(logs) {
        return getValueFromLogs({
            iface: accounts.iface.bosonAccountHandlerIface,
            logs,
            eventArgsKey: "disputeResolverId",
            eventName: "DisputeResolverCreated"
        });
    }
    /**
     * Utility method to retrieve the pending seller update fields from logs after calling `updateSeller`.
     * @param logs - Logs to search in.
     * @returns Created exchange id.
     */
    getPendingSellerUpdateFromLogs(logs) {
        // Extract fields pendingSeller and pendingAuthToken from
        // SellerUpdatePending or SellerUpdateApplied events
        const valuesFromLogs = getValuesFromLogsExt({
            iface: accounts.iface.bosonAccountHandlerIface,
            logs,
            eventArgsKeys: ["pendingSeller", "pendingAuthToken", "sellerId"],
            eventNames: ["SellerUpdatePending", "SellerUpdateApplied"]
        });
        const pendingSellerStruct = valuesFromLogs["pendingSeller"]?.[0];
        const pendingAuthTokenStruct = valuesFromLogs["pendingAuthToken"]?.[0];
        const sellerId = valuesFromLogs["sellerId"]?.[0];
        return {
            sellerId,
            assistant: pendingSellerStruct?.assistant,
            admin: pendingSellerStruct?.admin,
            clerk: pendingSellerStruct?.clerk,
            tokenId: pendingAuthTokenStruct?.tokenId,
            tokenType: pendingAuthTokenStruct?.tokenType
        };
    }
    // Implementation
    async updateDisputeResolver(disputeResolverId, updates, overrides = {}) {
        const { returnTxInfo } = overrides;
        const disputeArgs = {
            disputeResolverId,
            updates,
            subgraphUrl: this._subgraphUrl,
            contractAddress: overrides.contractAddress || this._protocolDiamond,
            web3Lib: this._web3Lib
        };
        if (returnTxInfo === true) {
            return accounts.handler.updateDisputeResolver({
                ...disputeArgs,
                returnTxInfo: true
            });
        }
        else {
            return accounts.handler.updateDisputeResolver({
                ...disputeArgs,
                returnTxInfo: false
            });
        }
    }
    // Implementation
    async optInToDisputeResolverUpdate(disputeResolverUpdates, overrides = {}) {
        const { returnTxInfo } = overrides;
        const disputeArgs = {
            disputeResolverUpdates,
            web3Lib: this._web3Lib,
            contractAddress: overrides.contractAddress || this._protocolDiamond
        };
        if (returnTxInfo === true) {
            return accounts.handler.optInToDisputeResolverUpdate({
                ...disputeArgs,
                returnTxInfo: true
            });
        }
        else {
            return accounts.handler.optInToDisputeResolverUpdate({
                ...disputeArgs,
                returnTxInfo: false
            });
        }
    }
    // Implementation
    async addFeesToDisputeResolver(disputeResolverId, fees, overrides = {}) {
        const { returnTxInfo } = overrides;
        const disputeArgs = {
            disputeResolverId,
            fees,
            contractAddress: overrides.contractAddress || this._protocolDiamond,
            web3Lib: this._web3Lib
        };
        if (returnTxInfo === true) {
            return accounts.handler.addFeesToDisputeResolver({
                ...disputeArgs,
                returnTxInfo: true
            });
        }
        else {
            return accounts.handler.addFeesToDisputeResolver({
                ...disputeArgs,
                returnTxInfo: false
            });
        }
    }
    // Implementation
    async addSellersToDisputeResolverAllowList(disputeResolverId, sellerAllowList, overrides = {}) {
        const { returnTxInfo } = overrides;
        const args = {
            disputeResolverId,
            sellerAllowList,
            contractAddress: this._protocolDiamond,
            web3Lib: this._web3Lib
        };
        if (returnTxInfo === true) {
            return accounts.handler.addSellersToAllowList({
                ...args,
                returnTxInfo: true
            });
        }
        else {
            return accounts.handler.addSellersToAllowList({
                ...args,
                returnTxInfo: false
            });
        }
    }
    // Implementation
    async removeFeesFromDisputeResolver(disputeResolverId, feeTokenAddresses, overrides = {}) {
        const { returnTxInfo } = overrides;
        const args = {
            disputeResolverId,
            feeTokenAddresses,
            contractAddress: this._protocolDiamond,
            web3Lib: this._web3Lib
        };
        if (returnTxInfo === true) {
            return accounts.handler.removeFeesFromDisputeResolver({
                ...args,
                returnTxInfo: true
            });
        }
        else {
            return accounts.handler.removeFeesFromDisputeResolver({
                ...args,
                returnTxInfo: false
            });
        }
    }
    // Implementation
    async removeSellersFromDisputeResolverAllowList(disputeResolverId, sellerAllowList, overrides = {}) {
        const { returnTxInfo } = overrides;
        const args = {
            disputeResolverId,
            sellerAllowList,
            contractAddress: this._protocolDiamond,
            web3Lib: this._web3Lib
        };
        if (returnTxInfo === true) {
            return accounts.handler.removeSellersFromAllowList({
                ...args,
                returnTxInfo: true
            });
        }
        else {
            return accounts.handler.removeSellersFromAllowList({
                ...args,
                returnTxInfo: false
            });
        }
    }
    /**
     * Returns dispute resolver entity from subgraph.
     * @param disputeResolverId - ID of dispute resolver entity to query for.
     * @param queryVars - Optional query variables to skip, order or filter.
     * @returns Dispute resolver entity from subgraph.
     */
    async getDisputeResolverById(disputeResolverId, queryVars) {
        return accounts.subgraph.getDisputeResolverById(this._subgraphUrl, disputeResolverId, queryVars);
    }
    /**
     * Returns dispute resolver entities from subgraph.
     * @param queryVars - Optional query variables to skip, order or filter.
     * @returns Dispute resolver entities from subgraph.
     */
    async getDisputeResolvers(queryVars) {
        return accounts.subgraph.getDisputeResolvers(this._subgraphUrl, queryVars);
    }
    async createNewCollection(collectionToCreate, overrides = {}) {
        const { returnTxInfo } = overrides;
        if (!collectionToCreate.sellerId) {
            const { id: sellerId } = await this.getSellerByAssistant(await this._web3Lib.getSignerAddress());
            // If the caller is not a seller, the sellerId remains undefined
            collectionToCreate.sellerId = sellerId;
        }
        const args = {
            collectionToCreate,
            web3Lib: this._web3Lib,
            contractAddress: overrides.contractAddress || this._protocolDiamond,
            theGraphStorage: this._theGraphStorage,
            metadataStorage: this._metadataStorage
        };
        if (returnTxInfo === true) {
            return accounts.handler.createNewCollection({
                ...args,
                returnTxInfo: true
            });
        }
        else {
            return accounts.handler.createNewCollection({
                ...args,
                returnTxInfo: false
            });
        }
    }
    async getOfferCollections(queryVars) {
        return accounts.subgraph.getOfferCollections(this._subgraphUrl, queryVars);
    }
    async addRoyaltyRecipients(sellerId, royaltyRecipients, overrides = {}) {
        const { returnTxInfo } = overrides;
        const args = {
            sellerId,
            royaltyRecipients,
            web3Lib: this._web3Lib,
            contractAddress: overrides.contractAddress || this._protocolDiamond
        };
        if (returnTxInfo === true) {
            return accounts.handler.addRoyaltyRecipients({
                ...args,
                returnTxInfo: true
            });
        }
        else {
            return accounts.handler.addRoyaltyRecipients({
                ...args,
                returnTxInfo: false
            });
        }
    }
    async updateRoyaltyRecipients(sellerId, royaltyRecipientIds, royaltyRecipients, overrides = {}) {
        const { returnTxInfo } = overrides;
        const args = {
            sellerId,
            royaltyRecipientIds,
            royaltyRecipients,
            web3Lib: this._web3Lib,
            contractAddress: overrides.contractAddress || this._protocolDiamond
        };
        if (returnTxInfo === true) {
            return accounts.handler.updateRoyaltyRecipients({
                ...args,
                returnTxInfo: true
            });
        }
        else {
            return accounts.handler.updateRoyaltyRecipients({
                ...args,
                returnTxInfo: false
            });
        }
    }
    async removeRoyaltyRecipients(sellerId, royaltyRecipientIds, overrides = {}) {
        const { returnTxInfo } = overrides;
        const args = {
            sellerId,
            royaltyRecipientIds,
            web3Lib: this._web3Lib,
            contractAddress: overrides.contractAddress || this._protocolDiamond
        };
        if (returnTxInfo === true) {
            return accounts.handler.removeRoyaltyRecipients({
                ...args,
                returnTxInfo: true
            });
        }
        else {
            return accounts.handler.removeRoyaltyRecipients({
                ...args,
                returnTxInfo: false
            });
        }
    }
    async getRoyaltyRecipients(sellerId, overrides = {}) {
        return accounts.handler.getRoyaltyRecipients({
            sellerId,
            web3Lib: this._web3Lib,
            contractAddress: overrides.contractAddress || this._protocolDiamond
        });
    }
}
//# sourceMappingURL=mixin.js.map