contract EMillionNfts is ERC721, Ownable {
    using SafeMath for uint256;
    address public WETH;
    using SafeERC20 for IERC20;
    uint96 royaltyFeesInBips;
    address royaltyAddress;

    mapping(uint256 => address) artist;

    mapping(uint256 => uint256) public nftInitialPrice;

    event initializeNftEvent(
        uint256 nftId,
        address indexed artist,
        address indexed nftAddress,
        uint256 nftInitPrice
    );

    event mint(
        uint256 nftId,
        address indexed owner,
        address indexed nftAddress
    );

    constructor(
        string memory name,
        string memory symbol,
        address _WETH,
        uint96 _royaltyFeesInBips
    ) ERC721(name, symbol) {
        WETH = _WETH;
        royaltyAddress = msg.sender;
        royaltyFeesInBips = _royaltyFeesInBips;
    }

    function setRoyaltyInfo(address _receiver, uint96 _royaltyFeesInBips)
        public
        onlyOwner
    {
        royaltyAddress = _receiver;
        royaltyFeesInBips = _royaltyFeesInBips;
    }

    function withdrawETH() external onlyOwner {
        uint256 balance = address(this).balance;
        require(balance > 0, "ETH balance is 0");
        msg.sender.transfer(address(this).balance);
    }

    function withdWETH() external onlyOwner {
        require(IERC20(WETH).balanceOf(address(this)) > 0, "low balance");
        IERC20(WETH).transfer(
            msg.sender,
            IERC20(WETH).balanceOf(address(this))
        );
    }

    function setBaseURI(string memory baseURI) external onlyOwner {
        _setBaseURI(baseURI);
    }

    function initializeNft(
        uint256 _nftId,
        uint256 _nftInitPrice,
        address _artist
    ) external onlyOwner {
        require(_nftInitPrice > 0, "input nft price greater than zero");
        require(_artist != address(0), "you are passing address zero");
        require(nftInitialPrice[_nftId] == 0, "nft already initialized");
        nftInitialPrice[_nftId] = _nftInitPrice;
        artist[_nftId] = _artist;

        emit initializeNftEvent(_nftId, _artist, address(this), _nftInitPrice);
    }

    /**
     * Mints NFT
     */
    function mintNFT(uint256 _nftId) external payable {
        require(
            msg.value >= nftInitialPrice[_nftId] && nftInitialPrice[_nftId] > 0,
            "you dont have sufficent balance to buy this nft"
        );
        require(artist[_nftId] != address(0), "artist address is not defined");
        IWETH(WETH).deposit{value: msg.value}();
        IWETH(WETH).transfer(
            artist[_nftId],
            (nftInitialPrice[_nftId]).mul(700).div(1000)
        );
        _safeMint(msg.sender, _nftId);
        emit mint(_nftId, msg.sender, address(this));
    }

    function getArtist(uint256 id) external view returns (address) {
        return artist[id];
    }

    function returnblock() public returns (uint256) {
        return block.number;
    }

    /// royality logic
    function royaltyInfo(uint256 _tokenId, uint256 _salePrice)
        external
        view
        virtual
        returns (address, uint256)
    {
        return (royaltyAddress, calculateRoyalty(_salePrice));
    }

    function calculateRoyalty(uint256 _salePrice)
        public
        view
        returns (uint256)
    {
        return (_salePrice / 10000) * royaltyFeesInBips;
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        override(ERC165)
        returns (bool)
    {
        return
            interfaceId == 0x2a55205a || super.supportsInterface(interfaceId);
    }

    function contractURI() public view returns (string memory) {
        return baseURI();
    }
}
function royaltyInfo(uint256 _tokenId, uint256 _salePrice)
    external
    view
    virtual
    returns (address, uint256)
{
    return (royaltyAddress, calculateRoyalty(_salePrice));
}

/// royality logic