// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;

//
// This is a private interface that is used to talk to the Penny Oracle.
// 
interface IPennyOracleV1 {
    /**
     * @dev Used to determine if this is the active penny oracle for the project. Projects using
     * this oracle should handle the case of the oracle being updated. Once this returns false, this
     * oracle will return a stale price. 
     */
    function pennyOracleStatus() external returns (bool bActive, address theContract, uint256 lastBlock);
    /**
     * @dev Used to update the penny price of Tfuel.
     */
    function pennyPriceTfuel() external view returns (uint256 pennyPrice, string memory pennyWei);
}


//
// This is a private interface that is used to talk to the Penny Oracle.
// 
interface IPayV1 {
    /**
     * @dev Used to return the commission information carved out for mint
     */
    function payMintInfo() external view returns (uint256 payAgent, uint256 payWebsite, uint256 delayBlocks, uint256 minMints);

    function payMint(uint256 _AgentId, uint256 _websiteId) external payable returns(uint256 tokenId);

    function payWithdraw() external returns(bool);

    function payWithdrawTitled() external returns(bool);

    function paySweep(address _anAccount) external returns(bool);

    function payTreasuryBalance() external view returns(uint256 BalanceWei);

    function payAgentBalance(address _account) external view returns(uint256 payBalanceWei, uint256 payDeadline, uint256 payCount);

    function payMintPrice() external view returns(uint256 mintTfuelWei);

    function payActive() external view returns (bool);

    // This one is a passthrough to the penny oracle.
    //function pennyPriceTfuel() external view returns (uint256 pricePenny, string memory weiPenny);

}

/*
This interface is an extension to the IPayV1. Here, the code has been upgraded to provide
a price list that can be queried.
*/
interface IPayV2 {
    // If the token is burnable
    function payBurn(uint256 _tokenId) external payable ;

    function payPrice(uint8 _index) external view returns(uint256 tfuelWei);

    function penniesSet(uint8 _index, uint256 _mintPennies) external;

    function penniesRead(uint8 _index) external view returns(uint256 pennies);
}




/*
This IMemV1 interface works with the IPayV1 interface above to give the full list of elements that are needed
to provide the membership functionality. The IPayV1 functions lika payMint

*/
interface IMemV1 {

    //
    // This function returns basic information about the membership. This info can be used to help
    // describe what the membership offers.
    //
    function memInfo() external view returns (uint256 renewPennies, uint256 penniesPerDay, uint256 mintHours, uint256 renewHours);

    //
    // Token holders will want to know how much time is left on the contract. If there is time left, the status
    // of the membership will be active.
    //
    function memIsTimeLeft(uint256 _tokenId) external view returns(bool bActive, uint256 remainingPrePaidHours, uint256 remainingIntrinsicHours);

    //
    // This routine returns the intrinsic value stored on the membership.
    //
    function memBalance(uint256 _tokenId) external view returns(uint256 BalanaceWei, uint256 UnsettledWei);

    //
    // Because memberships charge over time, there is intrinsic value stored on the membership. This function
    // provides a path for the token holder to settle his account and retrive the intrinsic value. Note that
    // if there are no prepaid hours on the contract for this token, the status of the membership will become
    // inactive after this function is called.
    //
    function memWithdraw(uint256 _tokenId) external returns(bool);

    //
    // This function allows the project owner to settle a membership. No funds are actually paid out, but rather
    // the funds that are owed to the project owner are assigned to the project owers address. Any remaining funds
    // are retained for the member.
    //
    function memSettleTitled(uint256 _tokenId) external;

    //
    // This function allows the project owner the ability to grant prepaid hours to a membership. 
    //
    function memGrantHours(uint256 _tokenId, uint256 _addHours) external;

    //
    // Anyone can call to renew a membership. The renew functionality allows someone to pay more than
    // the basic renew amount. Any extra Wei is applied as Intrinsic value for the membership.
    //
    function memRenew(uint256 _tokenId) external payable;

    //
    // This function returns the lock status. 
    //
    function memLockStatus(uint256 _tokenId) external view returns(bool bLockedState);

    //
    // This function allows the project owner to lock or unlock a membership. If the membership is 
    // locked, the holder will not be able to use the token for it's tokengating functionality.
    //
    function memLockToggle(uint256 _tokenId, bool _bState) external;

    //
    // This function returns the intrinsic value total for all memberships.
    //
    function memTreasuryBalance() external view returns(uint256 BalanceWei);
}



//TODO: Eventually the agent NFT will be rentable. Renting will be done on a token Id basis, thus we'll 
// have to query for the renter info.
interface IRegisterV1 {

    // price to register a new agent
    //function regPrice() external view returns(uint256 priceWei);

    // This routine allows an NFT owner to register an agent.
    function regAgent(uint256 _agentId, address _partnerAddr) external payable returns(uint256 partnerId);

    // This routine returns the agentId for the given address.
    function regLookupPartner(address _lookupAddr) external view returns(uint256 agentId);

    // Anyone that calls this function must validate that both returned values are not address(0)
    function regResolve(uint256 _agentId) external view returns(address founderAddr, address partnerAddr);

    // returns the number of registration slots remaining for NFT holder
    function regSlotsRemaining(uint256 _agentId) external view returns(uint256 count);
}

//
// If the NFT is open for minting, mintable will return true. The ownerLockToggle functionality
// allows the project owner to pause minting for any reason. Likewise, to turn minting back on,
// they call the toggle. Yet any other limitations within the contract that prevent minting
// will not be changed. Thus, if the NFT limit has been reached, toggling the lock will not
// change the fact that the contract is fully minted.
//
interface IMintV1 {
    function mintable() external view returns(bool bMintable);
    function ownerLockToggle() external;
}

interface ICountV1 {
    /**
     * @dev Used to get the total count of minted items
     */
    function totalSupply() external view returns(uint256 theTotalSupply);
}

//
// Anyone that wants to interact with The Gallery will need this functionality. It is expected
// that new NFT projects will be added, the number in the collection will be counted and the 
// high end software will want to query so they can be displayed.
// 
interface IGalleryV1 {

    /**
     * @dev Used to add NFT contract to list
     * @param _contract NFT project that supports Metadata Hash functionality
     */
    function Add(address _contract) external returns(bool bSuccess);

    /**
     * @dev Used to retrieve the count of addresses.
     */
    function countOf() external returns (uint256 uiCount);
    /**
     * @dev Used to retrieve the last _count number of contract addresses.
     * @param _index The starting index
     */
    function retrieve(uint256 _index) external returns(address addrContract);

    /**
     * @dev Used to get the address of the latest gallery.
     */
    function version() external view returns (address addrContract);
}

// 
// This is the public interface that an NFT project will need to impliment in order to satisfy the
// Metadata Hash project file reading. The NFT project will want to expose this interface through the
// IERC165 supportsInterface() call. 
//
// Note that the class that impliments this functionality will need to have an initilize routine that
// stores the information. Thus, the commented out projectUpdate() routine.
//
interface IMetadataV1 {
    /**
     * @dev Used to setup the root URI information and validation hash. 
     * @param _URI Website location where project file can be found
     * @param _Project Name of the project file without extension
     * @param _hash The SHA1 hash of the project file
     */
    //function projectUpdate(string calldata _URI, string calldata _Project, string calldata _hash) external;
    /**
     * @dev Index to working project.
     */
    function projectIndex() external returns(uint uiIndex);
    /**
     * @dev project data by index.
     * @param _uiIndex The index to the Metadata Hash project to retrieve
     */
    function projectData(uint _uiIndex) external returns(string memory URI, string memory Project,string memory hash);
    /**
     * @dev Most current project data.
     */
    function projectDataCurrent() external returns(string memory URI, string memory Project,string memory hash);
    /**
     * @dev Most current project base URI.
     */
    function projectBaseURI() external returns(string memory URI);
}

interface IERC721ExV1 {
    /**
     * @dev If contract is setup for sendlock functionality.
     */
    function IsSendLock() external returns (bool bSendLock);
    /**
     * @dev Used for getting the cost of a sendLockRegister() call.
     */
    function paySendLockPrice() external view returns(uint256 sendLockWei);
    /**
     * @dev Used for registering a sendlock address on a contract.
     */
    function sendLockRegister(address to, uint256 tokenId) external payable;

    /**
     * @dev If contract is setup for soulBound functionality.
     */
    function IsSoulBound() external returns (bool bSoulBound);
    function payBurnPrice() external view returns(uint256 burnTfuelWei);
    function payBurn(uint256 _tokenId) external payable ;
}

/*
Used for membership functionality. 
*/
interface IERC721ExV1M {

    function tokenOf(address _theOwner) external view returns (uint256 tokenId);
    /**
     * @dev If contract is setup for soulBound functionality.
     */
    function IsSoulBound() external returns (bool bSoulBound);
}

//
// This interface exposes the functions that a person would use to interact with the treasury
// of the smart contract. When it comes to the treasury, people will want to see:
// 
// - total in treasury
// - total reserved for the titled
// - total for NFT
//
// And, of course, they will want to get to their funds. There should be routines for both the 
// titled and a token holder to get to their funds. To assit the titled, there are two sweep routines.
// one will loop for a range of accounts, the second will target just the token Id in question.
//
// - routine for The Titled to claim funds
// - routine for token holder to claim funds
//
// - routine to sweep some accounts
// - routine to sweep an account
// 
interface ITreasuryV1 {

    /**
     * @dev Used to view the balance held in the treasruy. 
     */
    function tBalance() external view returns(uint256);
    /**
     * @dev Used to view the balance held by the Titled. 
     */
    function tBalanceTitled() external view returns(uint256);
    /**
     * @dev Used to view the balance held by an individual token. 
     */
    function tBalanceAccount(uint256 _tokenId) external view returns(uint256);

    /**
     * @dev Used by a token holder to withdraw the remaining balance. 
     */
    function tWithdrawBalance(uint256 _tokenId) external returns(bool);

    /**
     * @dev Used by either The Titled or the project owner to withdraw The Titled balance. 
     */
    function tWithdrawTitled() external returns(bool);
    /**
     * @dev Used by either The Titled or the project owner to capture outstanding balance from all accounts. 
     */
    function tSweep(uint256 _tokenId, uint256 _count) external;
    /**
     * @dev Used by either The Titled or the project owner to capture the outstanding balance of an account.
     */
    function tSweepOne(uint256 _tokenId) external;
}

interface ITesterV1 {
    function registerContract(address _addrTest) external;

    function owner() external view returns (address);
    function titled() external view returns (address);

}


