contract MferCribs is ERC721URIStorage, Ownable, AccessControl {
    using SafeMath for uint256;

    bytes32 public constant PRE_SALE_ROLE = keccak256("PRE_SALE_ROLE");
    string private contractUri;
    string private baseUri;
    uint8 private platformRoyalty;
    mapping(uint256 => uint256) tokenSalePrices;
    event TokenSold(
        uint256 tokenId,
        address from,
        address to,
        uint256 price,
        uint256 royaltyPaid
    );

    bool public saleIsActive = false;
    uint256 public MAX_MINT;
    uint256 public constant apePrice = 22000000000000000; //0.022 ETH
    uint256 public constant maxApePurchase = 8888;
    uint256 public totalMintNumber;

    function totalSupply() public view returns (uint256) {
        return totalMintNumber;
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override(ERC721, AccessControl)
        returns (bool)
    {
        return super.supportsInterface(interfaceId);
    }

    constructor() ERC721("Mfer Cribs", "MferCribs") {
      
        contractUri = "http://nft-stage-bwrld.s3-website.us-east-2.amazonaws.com/contract";
        baseUri = "http://nft-stage-bwrld.s3-website.us-east-2.amazonaws.com/ipfs/";

        MAX_MINT = 8888;

        totalMintNumber = 0;
        platformRoyalty = 5;

        _setupRole(DEFAULT_ADMIN_ROLE, msg.sender);
    }

    function contractURI() public view returns (string memory) {
        return contractUri;
    }

    function setContractUri(string memory newUri) public onlyOwner {
        contractUri = newUri;
    }

    function _baseURI() internal view override returns (string memory) {
        return baseUri;
    }

    function setBaseUri(string memory newUri) public onlyOwner {
        baseUri = newUri;
    }

    function withdraw() public onlyOwner {
        uint amount = address(this).balance;

        (bool success, ) = owner().call{value: amount}("");
        require(success, "Failed to send Ether");
    }

    function platformFee() public view returns (uint8) {
        return platformRoyalty;
    }

    function setPlatformFee(uint8 newFee) public onlyOwner {
        platformRoyalty = newFee;
    }

    function mintNFT(uint256 numberOfTokens) public payable {
        require(saleIsActive, "Sale must be active to mint");
        require(
            numberOfTokens <= maxApePurchase,
            "Can only mint x tokens at a time"
        );
        require(
            totalSupply().add(numberOfTokens) <= MAX_MINT,
            "Purchase would exceed max supply"
        );
        require(
            apePrice.mul(numberOfTokens) <= msg.value,
            "Ether value sent is not correct"
        );

        for (uint256 i = 0; i < numberOfTokens; i++) {
            uint256 mintIndex = totalSupply();
            if (totalSupply() < MAX_MINT) {
                require(!_exists(mintIndex), "Has already been minted");
                totalMintNumber = totalMintNumber + 1;
                _mint(msg.sender, mintIndex);
            }
        }
    }

    /*
     * Pause sale if active, make active if paused
     */
    function flipSaleState() public onlyOwner {
        saleIsActive = !saleIsActive;
    }

    function isApprovedForAll(address _owner, address _operator)
        public
        view
        override
        returns (bool isOperator)
    {
        // Whitelist OpenSea proxy contract for easy trading.

        return isApprovedForAll(_owner, _operator);
    }

    function _beforeTokenTransfer(
        address from,
        address to,
        uint256 tokenId
    ) internal override {
        super._beforeTokenTransfer(from, to, tokenId);
        if (tokenSalePrices[tokenId] > 0) {
            tokenSalePrices[tokenId] = 0;
        }
    }
}
function flipSaleState() public onlyOwner {
    saleIsActive = !saleIsActive;
}

/*
 * Pause sale if active, make active if paused
 */