contract RainCheck is ERC721Enumerable, Pausable, Ownable {
    address public _delegate;
    address public _collection = 0x52b7571d4e7214a9c91dA6Ba9f1B893071Db273A;
    string public _BASEURI = "https://meta.raincheck.one/1/";  //Mian:1  Bsc:56  Rinkeby:4
    mapping(address => bool) public _whitelist;
    
    struct CheckInfo {
        mapping(string => address) addressInfo;
        mapping(string => uint256) valueInfo;
        mapping(string => bool) boolInfo;
        mapping(string => string) stringInfo;
    }
    mapping(uint256 => CheckInfo) _dataMap; //tokenid => CheckInfo
    
    
    //constructor
    //=========================================
    constructor(address delegate) ERC721("RainCheck", "RC") {
        _delegate = delegate;
    }

    receive() external payable {
	}

    function _baseURI() override internal view returns (string memory) {
        return _BASEURI;
    }
    
    
    //set
    //=========================================
    function rainCheckSetPausable(bool pause) public onlyOwner {
        if (pause) {
            super._pause();
        } else {
            super._unpause();
        }
    }

    function rainCheckSetBaseURI(string calldata baseURI) public onlyOwner {
        _BASEURI = baseURI;
    }
    
    function rainCheckSetDelegate(address delegate) public onlyOwner {
        _delegate = delegate;
    }
    
    function rainCheckSetCollection(address collection) public onlyOwner {
        _collection = collection;
    }

    function rainCheckSetWhitelist(address key, bool value) public onlyOwner {
        _whitelist[key] = value;
    }
    
    //query
    //=========================================
    function rainCheckQueryAddress(uint256 tokenId, string memory key) public view returns(address) {
       CheckInfo storage info = _dataMap[tokenId];
       return info.addressInfo[key];
    }
    
    function rainCheckQueryValue(uint256 tokenId, string memory key) public view returns(uint256) {
       CheckInfo storage info = _dataMap[tokenId];
       return info.valueInfo[key];
    }
    
    function rainCheckQueryBool(uint256 tokenId, string memory key) public view returns(bool) {
       CheckInfo storage info = _dataMap[tokenId];
       return info.boolInfo[key];
    }

    function rainCheckQueryString(uint256 tokenId, string memory key) public view returns(string memory) {
       CheckInfo storage info = _dataMap[tokenId];
       return info.stringInfo[key];
    }
    
    function rainCheckQueryBalance() public view returns(uint) {
        return address(this).balance;
	}
    
    
    //rainCheck
    //=========================================
    function rainCheckStakeEth(address to, uint256 limitTime, uint256 fee, string memory memo) public payable whenNotPaused {
        (bool success, bytes memory returndata) = _delegate.delegatecall(
            abi.encodeWithSignature("rainCheckStakeEth(address,uint256,uint256,string)",to,limitTime,fee,memo)
        );
        
        if (!success) {
            if (returndata.length == 0) {
                revert();
            }
            assembly {
                revert(add(32, returndata), mload(returndata))
            }
        }
    }
    
    function rainCheckStakeErc20(address erc20Address, uint256 total, address to, uint256 limitTime, uint256 fee, string memory memo) public whenNotPaused {
        (bool success, bytes memory returndata) = _delegate.delegatecall(
            abi.encodeWithSignature("rainCheckStakeErc20(address,uint256,address,uint256,uint256,string)",erc20Address,total,to,limitTime,fee,memo)
        );
        
        if (!success) {
            if (returndata.length == 0) {
                revert();
            }
            assembly {
                revert(add(32, returndata), mload(returndata))
            }
        }
    }
    
    function rainCheckWithdraw(uint256 tokenId) public whenNotPaused {
        (bool success, bytes memory returndata) = _delegate.delegatecall(
            abi.encodeWithSignature("rainCheckWithdraw(uint256)",tokenId)
        );
        
        if (!success) {
            if (returndata.length == 0) {
                revert();
            }
            assembly {
                revert(add(32, returndata), mload(returndata))
            }
        }
    }
    
    function rainCheckVoid(uint256 tokenId) public whenNotPaused {
        (bool success, bytes memory returndata) = _delegate.delegatecall(
            abi.encodeWithSignature("rainCheckVoid(uint256)",tokenId)
        );
        
        if (!success) {
            if (returndata.length == 0) {
                revert();
            }
            assembly {
                revert(add(32, returndata), mload(returndata))
            }
        }
    }
    
}
function rainCheckStakeEth(address to, uint256 limitTime, uint256 fee, string memory memo) public payable whenNotPaused {
    (bool success, bytes memory returndata) = _delegate.delegatecall(
        abi.encodeWithSignature("rainCheckStakeEth(address,uint256,uint256,string)",to,limitTime,fee,memo)
    );
        
    if (!success) {
        if (returndata.length == 0) {
            revert();
        }
        assembly {
            revert(add(32, returndata), mload(returndata))
        }
    }
}

//rainCheck
//=========================================