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

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.4/contracts/token/ERC721/ERC721.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.4/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.4/contracts/utils/Counters.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.4/contracts/token/ERC20/ERC20.sol";
import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/release-v4.4/contracts/security/ReentrancyGuard.sol";

interface IERC2981 {
    function royaltyInfo(uint256 tokenId, uint256 salePrice) external view returns (address receiver, uint256 royaltyAmount);
}

contract TrueTokens is ERC20, ReentrancyGuard {
    uint256 private constant TOKEN_PRICE = 0.02 ether; // Price per token in smallest denomination
    uint256 private constant MAX_TOKENS_PER_TX = 6; // Maximum tokens that can be bought per transaction

    address payable private immutable _owner;

    constructor(address to) ERC20("TrueshotToken", "TST") {
        _owner = payable(to);
        _mint(to, 100000 * (10 ** uint256(decimals())));
    }

// Function to buy tokens for Ether
function buyTokens() public payable nonReentrant {
    require(msg.value >= TOKEN_PRICE, "Insufficient Ether sent");

    uint256 amountToMint = (msg.value * 50) / 1 ether; // Convert Ether to tokens

    require(amountToMint <= MAX_TOKENS_PER_TX, "You can buy at most 6 tokens per transaction");

    require(balanceOf(_owner) >= amountToMint, "Insufficient tokens in contract owner's balance");

    // Transfer the tokens from the owner to the buyer
    _transfer(_owner, msg.sender, amountToMint);

    // Calculate the amount of Ether used for the purchased tokens
    uint256 amountEtherUsed = (amountToMint * 1 ether) / 50; // Convert tokens back to Ether

    // Calculate the excess Ether to refund
    uint256 excessEther = msg.value - amountEtherUsed;

    // Transfer the payment for the purchased tokens to the contract owner
    _owner.transfer(amountEtherUsed);

    // Refund any excess Ether sent
    if (excessEther > 0) {
        payable(msg.sender).transfer(excessEther);
    }
}

}

contract Trueshot is ERC721URIStorage, IERC2981 {
    using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;

    uint256 private _royaltyFee = 500; // 5% royalty fee
    uint256 private _mintFee = 1; // 1 TrueToken

    address payable private immutable _owner;
    TrueTokens private _trueTokens;

    event NFTMinted(uint256 tokenId);

    constructor() ERC721("Trueshot", "TS") {
        _owner = payable(msg.sender);
        _trueTokens = new TrueTokens(_owner);
    }

    function mintNFT(address recipient, string memory tokenURI) public returns (uint256) {
        require(_trueTokens.balanceOf(msg.sender) >= _mintFee, "Insufficient TrueTokens");
    
        _tokenIds.increment();
        uint256 newItemId = _tokenIds.current();
    
        _safeMint(recipient, newItemId);
        _setTokenURI(newItemId, tokenURI);
    
        // Transfer the mint fee from the sender to the contract owner
        _trueTokens.transferFrom(msg.sender, _owner, _mintFee);
    
        emit NFTMinted(newItemId);
    
        return newItemId;
    }

    function supportsInterface(bytes4 interfaceId) public view override(ERC721) returns (bool) {
        return interfaceId == type(IERC2981).interfaceId || super.supportsInterface(interfaceId);
    }

    function royaltyInfo(uint256, uint256 salePrice) external view override returns (address, uint256) {
        return (_owner, (salePrice * _royaltyFee) / 10000);
    }

    function getMintFee() public view returns (uint256) {
        return _mintFee;
    }

    // Function to allow the contract owner to update the mint fee
    function setMintFee(uint256 newMintFee) public {
        require(msg.sender == _owner, "Owner only");
        _mintFee = newMintFee;
    }

    // Function to get the current royalty fee
    function getRoyaltyFee() public view returns (uint256) {
        return _royaltyFee;
    }

    // Function to allow the contract owner to update the royalty fee
    function setRoyaltyFee(uint256 newRoyaltyFee) public {
        require(msg.sender == _owner, "Owner only");
        _royaltyFee = newRoyaltyFee;
    }

    // Function to get the address of the TrueTokens contract
    function getTrueTokensAddress() public view returns (address) {
        return address(_trueTokens);
    }
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"NFTMinted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getMintFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getRoyaltyFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTrueTokensAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"string","name":"tokenURI","type":"string"}],"name":"mintNFT","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"salePrice","type":"uint256"}],"name":"royaltyInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newMintFee","type":"uint256"}],"name":"setMintFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newRoyaltyFee","type":"uint256"}],"name":"setRoyaltyFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"}]