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

import "inetworkv1.sol"; 
import "istandard.sol";
import "library.sol";
import "abs_ownable.sol"; 


abstract contract ERC165 is IERC165 {
    /**
     * @dev See {IERC165-supportsInterface}.
     */
    function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
        return interfaceId == type(IERC165).interfaceId;
    }
}

import "abs_metadatav1.sol";

//
// This contract is going to export all the interfaces that are needed to the sample
// contracts so they can act like they are interacting with the real contracts on the 
// blockchain. 
//
// The idea here is that the developer launches this contract before launching their
// own project. The addresses regsitered for different activities will act like they 
// need to for basic functionality.
//
// _theAgent = register a wallet from Remix that will be treated as an Agent
// _theWebsite = register a wallet from Remix that will be treated as the website
// _theParticipant = register a wallet from Remix that will be treated as the participant holder
//
//
contract TESTV1 is ERC165, ITesterV1 { //}, MetaDataV1, PayV1, ICountV1, IMintV1, IBurnV1  { 
    using Strings for uint256;

    // These represent token ids
    uint256 private constant WEBSITE_ID = 1;
    uint256 private constant PARTICIPANT_ID = 2;
    uint256 private constant TITLED_ID = 3;
    uint256 private constant OWNER_ID = 4;
    uint256 private constant PARTICIPANT2_ID = 5;
    uint256 private constant AGENT_ID = 1001;

    address private m_addrParticipant; // account that holds a participant NFT
    uint256 private m_idParticipant;   // Id
    address private m_addrParticipant2; // account that holds a participant NFT
    uint256 private m_idParticipant2;   // Id

    address private m_addrAgent; // Partner Agent account that recieves commissions
    uint256 private m_idAgent;   // Id of that partner agent

    address private m_addrWebsite; // account that will be seen as the website id holder (recieves commissions)
    uint256 private m_idWebsite;   // Id

    // These two accounts will be seen as holding Participant NFTs
    address private m_addrTitled; 
    uint256 private m_idTitled; 
    address private m_addrOwner; 
    uint256 private m_idOwner; 

    // the test contract can be registered too. 
    address private m_addrTest;
    uint256 private m_idTest;


    // used for Penny Oracle calls.
    uint256 private m_tfuelWei;      // this is an integer of Wei like 260060000000000000, a penny's worth of tfuel
    string private m_strTfuelPrice;  // this is a price string like 0.0456 (tfuel/dollar)



    constructor(address _theTitled,
                address _theParticipant,
                address _theAgent, 
                address _theWebsite,
                address _theParticipant2,
                uint256 _PennyWorthOfTfuel,
                string memory _strMarketPriceOfTfuel)
        {

            // for IPennyOracleV1
            m_tfuelWei=_PennyWorthOfTfuel;
            m_strTfuelPrice=_strMarketPriceOfTfuel;

            // for IRegisterV1
            if( _theAgent != address(0)) {
                m_addrAgent = _theAgent;
                m_idAgent = AGENT_ID;
            }
            // For token ownership calls
            if( _theWebsite != address(0)) {
                m_addrWebsite = _theWebsite;
                m_idWebsite = WEBSITE_ID;
            }
            if( _theParticipant != address(0)) {
                m_addrParticipant = _theParticipant;
                m_idParticipant = PARTICIPANT_ID;
            }

            if( _theTitled == address(0) ) {
                m_addrTitled = msg.sender;
                m_idTitled = TITLED_ID;
            } else {
                m_addrTitled = _theTitled;
                m_idTitled = TITLED_ID;
            }

            if( _theParticipant2 != address(0)) {
                m_addrParticipant2 = _theParticipant2;
                m_idParticipant2 = PARTICIPANT2_ID;
            }


            m_addrOwner =msg.sender;
            m_idOwner = OWNER_ID;
        }

    // add and subtract functions
    function add(uint256 _a, uint256 _b) public pure returns(uint256 result) {
        return (_a + _b);
    }
    function sub(uint256 _root, uint256 _remove) public pure returns(uint256 result) {
        return (_root-_remove);
    }

    // ---- ITesterV1 ---

    function registerContract(address _addrTest) external {
        m_addrTest = _addrTest;
    }
    function owner() external view returns (address) {
        return m_addrOwner;
    }
    function titled() external view returns (address) {
        return m_addrOwner;
    }


    // --------------------------  IPennyOracleV1 --------------------------
    function pennyOracleStatus() external view returns (bool bActive, address theContract, uint256 lastBlock) {
        return (true,address(this), 0);
    }
    /**
     * @dev Used to retrieve the penny price of tfuel.
     */
    function pennyPriceTfuel() external view returns (uint256 _pennyTfuelWei, string memory _priceOfTfuel) {
        return (m_tfuelWei,m_strTfuelPrice);
    }
    // --------------------------  IPennyOracleV1 --------------------------

    // --------------------------  IRegisterV1 --------------------------
    // We return that are agent id is AGENT_ID
    function regLookupPartner(address _lookupAddr) external view returns(uint256 agentId) {
        agentId = 0;
        if( _lookupAddr == m_addrAgent) {
            agentId = m_idAgent;
        }
        return agentId;
    }

    // We report that we are a founder and partner agent
    function regResolve(uint256 _agentId) external view returns(address founderAddr, address partnerAddr) {
        if( AGENT_ID == _agentId) {
            return (m_addrAgent,m_addrAgent);
        } else {
            return (address(0),address(0));
        }
    }
    // --------------------------  IPennyOracleV1 --------------------------

    // -------------------------- IERC721 -------------------------------

    //
    // When we're acting like a participant contract, all our registered addresses will
    // return that they hold a balance.
    //
    function balanceOf(address _account) public view returns(uint256 balance) {
        uint256 uiBalance = 0;
        if( _account == m_addrAgent ) {
            uiBalance = 1;
        } else if( _account == m_addrWebsite ) {
            uiBalance = 1;
        } else if( _account == m_addrParticipant ) {
            uiBalance = 1;
        } else if( _account == m_addrParticipant2 ) {
            uiBalance = 1;
        } else if( _account == m_addrTitled ) {
            uiBalance = 1;
        } else if( _account == m_addrOwner ) {
            uiBalance = 1;
        } else if( _account == m_addrTest ) {
            uiBalance = 1;
        }
        return uiBalance;
    }

    // This should only be called in the case of getting the website item
    function ownerOf(uint256 _tokenId) public view returns(address addrOwner) {
        address addrRet = address(0);
        if( _tokenId == m_idWebsite) {
            addrRet = m_addrWebsite;
        } else if( _tokenId == m_idAgent) {
            addrRet = m_addrAgent;
        } else if( _tokenId == m_idParticipant) {
            addrRet = m_addrParticipant;
        } else if( _tokenId == m_idTitled) {
            addrRet = m_addrTitled;
        } else if( _tokenId == m_idOwner) {
            addrRet = m_addrOwner;
        } else if( _tokenId == m_idParticipant2) {
            addrRet = m_addrParticipant2;
        }
        return addrRet;
    }

    // -------------------------- IERC721 -------------------------------


    //
    // This test environment is going to act like all the interfaces we need to interact with.
    // 
    function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
        return
            interfaceId == type(IPennyOracleV1).interfaceId ||
            super.supportsInterface(interfaceId);
    }

    //
    // This code is used to get the interface ids for high level querys
    //
    function interfaces(uint256 _index) public pure returns(bytes4) {

        bytes4 _ret = 0;
        if( 0 == _index) {
            _ret =  type(IMetadataV1).interfaceId;
        } else if( 1 == _index) {
            _ret =  type(IPayV1).interfaceId;
        } else if( 2 == _index) {
            _ret =  type(IPayV2).interfaceId;
        } else if( 3 == _index) {
            _ret =  type(IMintV1).interfaceId;
        } else if( 4 == _index) {
            _ret =  type(ICountV1).interfaceId;
        } else if( 5 == _index) {
            _ret =  type(IPennyOracleV1).interfaceId;
        } else if( 6 == _index) {
            _ret =  type(IERC721ExV1).interfaceId;
        } else if( 7 == _index) {
            _ret =  type(IMemV1).interfaceId;
        } else if( 8 == _index) {
            _ret =  type(IERC721ExV1M).interfaceId;
        } else if( 9 == _index) {
            _ret =  type(IERC721).interfaceId;
        } else if( 10 == _index) {
            _ret =  type(IERC165).interfaceId;
        } else if( 11 == _index) {
            _ret =  type(IERC721Metadata).interfaceId;
        } else if( 12 == _index) {
            _ret =  type(ISelNetV1).interfaceId;
        }    
        return _ret;
    }

}

