// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.9;

/// @title IMetaAlgorithm a interface to call algorithms contracts
/// @author JorgeLpzGnz & CarlosMario714
/// @dev the algorithm is responsible for calculating the prices see
interface IMetaAlgorithm {

    /// @dev See each algorithm to see how this values are calculated

    /// @notice it returns the name of the Algorithm
    function name() external pure returns( string memory );

    /// @notice it checks if the start price is valid 
    function validateStartPrice( uint _startPrice ) external pure returns( bool );

    /// @notice it checks if the multiplier is valid 
    function validateMultiplier( uint _multiplier ) external pure returns( bool );

    /// @notice Return the necessary information to sell NFTs
    /// @param _multiplier Current multiplier used to calculate the price
    /// @param _startPrice Current start price used to calculate the price
    /// @param _numItems Number of NFTs to trade
    /// @param _protocolFee Fee multiplier to calculate the protocol fee
    /// @param _poolFee Fee multiplier to calculate the pool fee
    /// @return isValid True if trade can be performed
    /// @return newStartPrice New start price used to calculate the price
    /// @return newMultiplier New multiplier used to calculate the price
    /// @return inputValue Amount to send to the pool
    /// @return protocolFee Amount to charged for the trade
    function getBuyInfo( uint128 _multiplier, uint128 _startPrice, uint _numItems, uint128 _protocolFee, uint128 _poolFee ) external pure 
        returns ( 
            bool isValid, 
            uint128 newStartPrice, 
            uint128 newMultiplier, 
            uint256 inputValue, 
            uint256 protocolFee 
        );

    /// @notice Return the necessary information to sell NFTs
    /// @param _multiplier Current multiplier used to calculate the price
    /// @param _startPrice Current start price used to calculate the price
    /// @param _numItems Number of NFTs to trade
    /// @param _protocolFee Fee multiplier to calculate the protocol fee
    /// @param _poolFee Fee multiplier to calculate the pool fee
    /// @return isValid True if trade can be performed
    /// @return newStartPrice New start price used to calculate the price
    /// @return newMultiplier New multiplier used to calculate the price
    /// @return outputValue Amount to send to the user
    /// @return protocolFee Amount to charged for the trade
    function getSellInfo( uint128 _multiplier, uint128 _startPrice, uint _numItems, uint128 _protocolFee, uint128 _poolFee ) external pure
        returns ( 
            bool isValid, 
            uint128 newStartPrice, 
            uint128 newMultiplier, 
            uint256 outputValue, 
            uint256 protocolFee 
        );

}
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"amountIn","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"outputNFTs","type":"uint256"}],"name":"BuyLog","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"nft","type":"address"},{"indexed":false,"internalType":"uint256","name":"tokenID","type":"uint256"}],"name":"NFTDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"AmountOfNFTs","type":"uint256"}],"name":"NFTWithdrawal","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newRecipient","type":"address"}],"name":"NewAssetsRecipient","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"newMultiplier","type":"uint128"}],"name":"NewMultiplier","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"newStartPrice","type":"uint128"}],"name":"NewStartPrice","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"newFee","type":"uint256"}],"name":"NewTradeFee","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"inputNFTs","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOut","type":"uint256"}],"name":"SellLog","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TokenDeposit","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint256","name":"withdrawAmount","type":"uint256"}],"name":"TokenWithdrawal","type":"event"},{"inputs":[],"name":"Algorithm","outputs":[{"internalType":"contract IMetaAlgorithm","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_TRADE_FEE","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NFT","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentPoolType","outputs":[{"internalType":"enum PoolTypes.PoolType","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"contract IMetaFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAlgorithmInfo","outputs":[{"internalType":"contract IMetaAlgorithm","name":"algorithm","type":"address"},{"internalType":"string","name":"name","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAssetsRecipient","outputs":[{"internalType":"address","name":"_recipient","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getNFTIds","outputs":[{"internalType":"uint256[]","name":"nftIds","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_numNFTs","type":"uint256"}],"name":"getPoolBuyInfo","outputs":[{"internalType":"bool","name":"isValid","type":"bool"},{"internalType":"uint128","name":"newStartPrice","type":"uint128"},{"internalType":"uint128","name":"newMultiplier","type":"uint128"},{"internalType":"uint256","name":"inputValue","type":"uint256"},{"internalType":"uint256","name":"protocolFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPoolInfo","outputs":[{"internalType":"uint128","name":"poolMultiplier","type":"uint128"},{"internalType":"uint128","name":"poolStartPrice","type":"uint128"},{"internalType":"uint128","name":"poolTradeFee","type":"uint128"},{"internalType":"address","name":"poolNft","type":"address"},{"internalType":"uint256[]","name":"poolNFTs","type":"uint256[]"},{"internalType":"contract IMetaAlgorithm","name":"poolAlgorithm","type":"address"},{"internalType":"string","name":"poolAlgorithmName","type":"string"},{"internalType":"enum PoolTypes.PoolType","name":"poolPoolType","type":"uint8"},{"internalType":"address","name":"assetsRecipient","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_numNFTs","type":"uint256"}],"name":"getPoolSellInfo","outputs":[{"internalType":"bool","name":"isValid","type":"bool"},{"internalType":"uint128","name":"newStartPrice","type":"uint128"},{"internalType":"uint128","name":"newMultiplier","type":"uint128"},{"internalType":"uint256","name":"outputValue","type":"uint256"},{"internalType":"uint256","name":"protocolFee","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint128","name":"_multiplier","type":"uint128"},{"internalType":"uint128","name":"_startPrice","type":"uint128"},{"internalType":"address","name":"_recipient","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_NFT","type":"address"},{"internalType":"uint128","name":"_fee","type":"uint128"},{"internalType":"contract IMetaAlgorithm","name":"_Algorithm","type":"address"},{"internalType":"enum PoolTypes.PoolType","name":"_poolType","type":"uint8"}],"name":"init","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"multiplier","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"id","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"recipient","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newRecipient","type":"address"}],"name":"setAssetsRecipient","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"_newMultiplier","type":"uint128"}],"name":"setMultiplier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"_newStartPrice","type":"uint128"}],"name":"setStartPrice","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint128","name":"_newFee","type":"uint128"}],"name":"setTradeFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"startPrice","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIDs","type":"uint256[]"},{"internalType":"uint256","name":"_minExpectedOut","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"swapNFTsForToken","outputs":[{"internalType":"uint256","name":"outputAmount","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_numNFTs","type":"uint256"},{"internalType":"uint256","name":"_maxExpectedIn","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"swapTokenForAnyNFT","outputs":[{"internalType":"uint256","name":"inputAmount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256[]","name":"_tokenIDs","type":"uint256[]"},{"internalType":"uint256","name":"_maxExpectedIn","type":"uint256"},{"internalType":"address","name":"_user","type":"address"}],"name":"swapTokenForNFT","outputs":[{"internalType":"uint256","name":"inputAmount","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"tradeFee","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC721","name":"_nft","type":"address"},{"internalType":"uint256[]","name":"_nftIds","type":"uint256[]"}],"name":"withdrawNFTs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdrawTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]