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 { ethers } from "ethers";
import { erc20Allowance } from "../erc20";
import { pad0xBegin } from "../../../utils/common/utils";
import { toHexAndPadLeft, padLeft } from "../../../utils/ethers/utils";
import { getContractAddressAndAbiByContractName, triggerContractByContractName, viewContractByContractName, } from "../../../utils/ethers/contractHelper";
import { LandId } from "../../../config/constants";
import { getAddressesByLandId } from "../../../utils/ethers/addressHelper";
/**
 * Apostle Allowance To Clock Auction
 * @param provider Ethers provider
 * @param from From
 * @param callback Callback
 * @returns Promise<string | undefined>
 */
export const apostleAllowanceToClockAuction = (landId, provider, from, callback) => __awaiter(void 0, void 0, void 0, function* () {
    const spender = getContractAddressAndAbiByContractName(landId, provider, "apostleAuction").address;
    if (spender) {
        return erc20Allowance(landId, provider, "ring", from, spender);
    }
    else {
        callback &&
            callback.errorCallback({ error: new Error("failed to call apostleAllowanceToClockAuction. spender undefined") });
    }
});
/**
 * Apostle Bid
 * @param signer Ethers signer
 * @param tokenId Apostle token id
 * @param referrer Refer address
 * @param amountMax RING Amount
 * @param callback Callback
 */
export const apostleBidWithToken = (landId, signer, tokenId, referrer, amountMax, callback) => {
    const finalReferrer = referrer && ethers.utils.isAddress(referrer) ? referrer : "0x0000000000000000000000000000000000000000";
    if (landId === LandId.ETHEREUM || landId === LandId._ETHEREUM) {
        const data = referrer
            ? `${pad0xBegin(tokenId)}${ethers.utils.hexZeroPad(referrer, 32).slice(2)}`
            : pad0xBegin(tokenId);
        const addresses = getAddressesByLandId(landId);
        if (!addresses || !addresses.APOSTLE_CLOCK_AUCTION) {
            throw "address error";
        }
        return triggerContractByContractName(landId, signer, "ring", "transfer(address,uint256,bytes)", [addresses.APOSTLE_CLOCK_AUCTION, amountMax, data], callback);
    }
    return triggerContractByContractName(landId, signer, "apostleClockAuctionV3", "bidWithToken", [pad0xBegin(tokenId), finalReferrer, amountMax], callback);
};
/**
 * Apostle Breed - Apostle reproduction in own
 * @param signer Ethers signer
 * @param tokenId Token id
 * @param targetTokenId Target token id
 * @param amountMax Amount max
 * @param callback Callback
 */
export const apostleBreed = (landId, signer, tokenId, targetTokenId, amountMax, callback) => {
    if (landId === LandId.ETHEREUM || landId === LandId._ETHEREUM) {
        const addresses = getAddressesByLandId(landId);
        if (!addresses || !addresses.APOSTLE_BASE) {
            throw "address error";
        }
        return triggerContractByContractName(landId, signer, "ring", "transfer(address,uint256,bytes)", [
            addresses.APOSTLE_BASE,
            amountMax,
            `${pad0xBegin(tokenId)}${ethers.utils.hexZeroPad(pad0xBegin(targetTokenId), 32).slice(2)}`,
        ], callback);
    }
    return triggerContractByContractName(landId, signer, "apostleBaseV3", "breedWithAuto", [pad0xBegin(tokenId), pad0xBegin(targetTokenId), amountMax], callback);
};
/**
 * Apostle Breed Bid - Apostle reproduction
 * @param signer Ethers signer
 * @param tokenId Token id
 * @param targetTokenId Target token id
 * @param amountMax Amount max (bidPrice + autoBirthFee)
 * @param callback Callback
 */
export const apostleBreedBid = (landId, signer, tokenId, targetTokenId, amountMax, callback) => {
    if (landId === LandId.ETHEREUM || landId === LandId._ETHEREUM) {
        const addresses = getAddressesByLandId(landId);
        if (!addresses || !addresses.SIRING_CLOCK_AUCTION) {
            throw "address error";
        }
        return triggerContractByContractName(landId, signer, "ring", "transfer(address,uint256,bytes)", [
            addresses.SIRING_CLOCK_AUCTION,
            amountMax,
            `${pad0xBegin(tokenId)}${ethers.utils.hexZeroPad(pad0xBegin(targetTokenId), 32).slice(2)}`,
        ], callback);
    }
    return triggerContractByContractName(landId, signer, "apostleSiringAuctionV3", "bidWithToken", [pad0xBegin(tokenId), pad0xBegin(targetTokenId), amountMax], callback);
};
/**
 * Apostle Hire Bid - Bid apostle on Renting
 * @param signer Ethers signer
 * @param tokenId Apostle token id
 * @param amountMax Amount max (bid price)
 * @param callback Callback
 */
export const apostleHireBid = (landId, signer, tokenId, amountMax, callback) => {
    if (landId === LandId.ETHEREUM || landId === LandId._ETHEREUM) {
        const addresses = getAddressesByLandId(landId);
        if (!addresses || !addresses.TOKEN_USE) {
            throw "address error";
        }
        return triggerContractByContractName(landId, signer, "ring", "transfer(address,uint256,bytes)", [addresses.TOKEN_USE, amountMax, pad0xBegin(tokenId)], callback);
    }
    return triggerContractByContractName(landId, signer, "apostleTokenUseV2", "takeTokenUseOffer", [pad0xBegin(tokenId), amountMax], callback);
};
/**
 * Apostle Born Without Element
 * @param signer Ethers signer
 * @param motherTokenId Mother token id
 * @param callback Callback
 */
export const apostleBorn = (landId, signer, motherTokenId, callback) => {
    return triggerContractByContractName(landId, signer, "apostleBaseV3", "giveBirth", [pad0xBegin(motherTokenId), ethers.utils.hexZeroPad("0x", 20), 0, 0], callback);
};
/**
 * Apostle Born And Enhance
 * @param signer Ethers signer
 * @param motherTokenId Mother token id
 * @param element Element
 * @param level Level
 * @param levelUnitPrice Level unit price
 * @param callback Callback
 * @returns Void
 */
export const apostleBornAndEnhance = (landId, signer, motherTokenId, element, level, levelUnitPrice, callback) => __awaiter(void 0, void 0, void 0, function* () {
    const elementAddress = getContractAddressAndAbiByContractName(landId, signer, element).address;
    const cost = ethers.BigNumber.from(level).mul(ethers.BigNumber.from(levelUnitPrice)).toString();
    if (landId === LandId.ETHEREUM || landId === LandId._ETHEREUM) {
        const addresses = getAddressesByLandId(landId);
        if (!addresses || !addresses.APOSTLE_BASE) {
            throw "address error";
        }
        return triggerContractByContractName(landId, signer, element, "transfer(address,uint256,bytes)", [
            addresses.APOSTLE_BASE,
            cost,
            `${pad0xBegin(motherTokenId)}${ethers.utils.hexZeroPad(ethers.utils.hexlify(level), 32).slice(2)}`,
        ], callback);
    }
    return triggerContractByContractName(landId, signer, "apostleBaseV3", "giveBirth", [pad0xBegin(motherTokenId), elementAddress, level, cost], callback);
});
/**
 * Returns the current price of an auction.
 * @param provider Ethers signer
 * @param tokenId Apostle Token Id
 * @param callback Callback
 * @returns any
 */
export const apostleGetCurrentPriceByTokenId = (landId, provider, tokenId, callback) => __awaiter(void 0, void 0, void 0, function* () {
    const results = yield viewContractByContractName(landId, provider, "apostleClockAuctionV3", "getCurrentPriceInToken", [pad0xBegin(tokenId)], callback);
    return results[0].toHexString();
});
/**
 * Returns the current siring price of an auction.
 * @param provider Ethers signer
 * @param tokenId Token Id
 * @param callback Callback
 * @returns any
 */
export const apostleGetCurrentSiringPriceByTokenId = (landId, provider, tokenId, callback) => __awaiter(void 0, void 0, void 0, function* () {
    const results = yield viewContractByContractName(landId, provider, "apostleSiringAuctionV3", "getCurrentPriceInToken", [pad0xBegin(tokenId)], callback);
    return results[0].toHexString();
});
/**
 * Sell Apostle asset
 * @param signer Ethers signer
 * @param from
 * @param tokenId - Apostle tokenId
 * @param start - start price
 * @param end - end price
 * @param duration - bid duration time in second
 * @param callback Callback
 * @returns {Promise<void>}
 */
export const apostleAskWithToken = (landId, signer, from, tokenId, startPrice, endPrice, duration, callback) => __awaiter(void 0, void 0, void 0, function* () {
    const _from = padLeft(from.slice(2), 64, "0");
    const _start = toHexAndPadLeft(startPrice).slice(2);
    const _end = toHexAndPadLeft(endPrice).slice(2);
    const _duration = toHexAndPadLeft(duration).slice(2);
    const data = `0x${_start}${_end}${_duration}${_from}`;
    const apostleClockAuctionV3 = getContractAddressAndAbiByContractName(landId, signer, "apostleClockAuctionV3");
    return triggerContractByContractName(landId, signer, "objectOwnership", "approveAndCall", [apostleClockAuctionV3.address, pad0xBegin(tokenId), data], callback);
});
/**
 * Cancel the auction by apostle token ID
 * @param landId Land Id
 * @param signer Signer
 * @param tokenId apostle token Id
 * @param callback Callback
 * @returns any
 */
export const apostleCancelAskWithToken = (landId, signer, tokenId, callback) => {
    return triggerContractByContractName(landId, signer, "apostleAuction", "cancelAuction", [pad0xBegin(tokenId)], callback);
};
/**
 * Renting apostles to work
 * @param landId Land Id
 * @param signer Signer
 * @param resourceAddress Resource contract address
 * @param tokenId Apostle tokenId
 * @param price Hire price
 * @param duration Duration in second
 * @param callback Callback
 */
export const apostleHire = (landId, signer, resourceAddress, tokenId, price, duration, callback) => __awaiter(void 0, void 0, void 0, function* () {
    const _price = toHexAndPadLeft(price).slice(2);
    const _duration = toHexAndPadLeft(duration).slice(2);
    const _resourceAddress = padLeft(resourceAddress.slice(2), 64, "0");
    const data = `0x${_duration}${_price}${_resourceAddress}`;
    const apostleTokenUseV2Contract = getContractAddressAndAbiByContractName(landId, signer, "apostleTokenUseV2");
    return triggerContractByContractName(landId, signer, "objectOwnership", "approveAndCall", [apostleTokenUseV2Contract.address, pad0xBegin(tokenId), data], callback);
});
/**
 * Cancel an apostle on Renting
 * @param landId Land Id
 * @param signer Signer
 * @param tokenId Apostle tokenId
 * @param callback Callback
 * @returns any
 */
export const apostleCancelHire = (landId, signer, tokenId, callback) => {
    return triggerContractByContractName(landId, signer, "apostleTokenUseV2", "cancelTokenUseOffer", [pad0xBegin(tokenId)], callback);
};
/**
 * Let apostle go to work
 * @param landId Land Id
 * @param signer Signer
 * @param apostleTokenId Apostle token Id
 * @param landTokenId Land token Id
 * @param elementContractAddress Element contract address
 * @param callback Callback
 * @returns any
 */
export const apostleWork = (landId, signer, apostleTokenId, landTokenId, elementContractAddress, callback) => {
    return triggerContractByContractName(landId, signer, "apostleLandResource", "startMining", [pad0xBegin(apostleTokenId), pad0xBegin(landTokenId), elementContractAddress], callback);
};
/**
 * Stop apostle mining
 * @param landId Land Id
 * @param signer Signer
 * @param tokenId Apostle tokenId
 * @param callback Callback
 * @returns any
 */
export const apostleStopWork = (landId, signer, tokenId, callback) => __awaiter(void 0, void 0, void 0, function* () {
    return triggerContractByContractName(landId, signer, "apostleLandResource", "stopMining", [pad0xBegin(tokenId)], callback);
});
/**
 * Get apostle breed fee
 * @param landId Land Id
 * @param provider Provider
 * @param callback Callback
 * @returns fee in string
 */
export const apostleGetAutoBreedFee = (landId, provider, callback) => __awaiter(void 0, void 0, void 0, function* () {
    const results = yield viewContractByContractName(landId, provider, "settingsRegistry", "uintOf", ["0x55494e545f4155544f42495254485f4645450000000000000000000000000000"], // UINT_AUTOBIRTH_FEE
    callback);
    return results[0].toHexString();
});
/**
 * Receive apostle
 * @param landId Land Id
 * @param signer Singer
 * @param tokenId Apostle tokenId
 * @param callback Callback
 * @returns any
 */
export const apostleClaim = (landId, signer, tokenId, callback) => __awaiter(void 0, void 0, void 0, function* () {
    return triggerContractByContractName(landId, signer, "apostleAuction", "claimApostleAsset", [pad0xBegin(tokenId)], callback);
});
/**
 * Apostle Breed Auction
 * @param landId Land Id
 * @param signer Signer
 * @param from Apostle owner
 * @param tokenId Apostle tokenId
 * @param startPrice Start price
 * @param endPrice End price
 * @param duration Auction duration time in second
 * @param callback Callback
 * @returns any
 */
export const apostleBreedAsk = (landId, signer, from, tokenId, startPrice, endPrice, duration, callback) => __awaiter(void 0, void 0, void 0, function* () {
    const _from = padLeft(from.slice(2), 64, "0");
    const _start = toHexAndPadLeft(startPrice).slice(2);
    const _end = toHexAndPadLeft(endPrice).slice(2);
    const _duration = toHexAndPadLeft(duration).slice(2);
    const data = `0x${_start}${_end}${_duration}${_from}`;
    const apostleSiringAuctionV3Contract = getContractAddressAndAbiByContractName(landId, signer, "apostleSiringAuctionV3");
    return triggerContractByContractName(landId, signer, "objectOwnership", "approveAndCall", [apostleSiringAuctionV3Contract.address, pad0xBegin(tokenId), data], callback);
});
/**
 * Cancel Apostle Breed Auction
 * @param landId Land Id
 * @param signer Signer
 * @param tokenId Apostle tokenId
 * @param callback Callback
 * @returns any
 */
export const apostleCancelBreedAsk = (landId, signer, tokenId, callback) => __awaiter(void 0, void 0, void 0, function* () {
    return triggerContractByContractName(landId, signer, "apostleSiringAuctionV3", "cancelAuction", [pad0xBegin(tokenId)], callback);
});
/**
 * Transfer Apsotle
 * @param landId Land Id
 * @param signer Signer
 * @param from Apostle owner
 * @param to Recipient
 * @param tokenId Apostle tokenId
 * @param callback Callback
 * @returns any
 */
export const apostleTransfer = (landId, signer, from, to, tokenId, callback) => __awaiter(void 0, void 0, void 0, function* () {
    return triggerContractByContractName(landId, signer, "objectOwnership", "transferFrom", [from, to, pad0xBegin(tokenId)], callback);
});
/**
 * Claim an apostle that expires at work
 * @param landId Land Id
 * @param signer Signer
 * @param tokenId Apostle tokenId
 * @param callback Callback
 * @returns any
 */
export const apostleClaimHire = (landId, signer, tokenId, callback) => __awaiter(void 0, void 0, void 0, function* () {
    return triggerContractByContractName(landId, signer, "apostleTokenUseV2", "removeTokenUseAndActivity", [pad0xBegin(tokenId)], callback);
});
