contract SURREAL is CF_ERC721 {
    
    using Strings for uint256;

    bool private _reveal = false;

    uint256 private _whitePrice = 100000000000000000;
    uint256 private _publicPrice = 150000000000000000;

    mapping(address => uint256) private _userWhiteMints; //How many times did the user mint in white lsit minting

    uint256 private _whiteMinted;

    mapping(address => bool) private _whiteAccess;
    
    constructor() {
        _mint(0x81cc8A4bb62fF93f62EC94e3AA40A3A862c54368, 10);
    }

    //Read Functions======================================================================================================================================================

    function tokenURI(uint256 tokenId) external view override returns (string memory) {
        if(!_reveal) {return string(abi.encodePacked(uriLink, "secret.json"));}
        
        ++tokenId;
        return string(abi.encodePacked(uriLink, tokenId.toString(), ".json"));

    }

    function prices() public view returns(uint256 whitePrice, uint256 publicPrice) {
        whitePrice = _whitePrice;
        publicPrice = _publicPrice;
    }

    function whiteListed(address user) external view returns(bool listed) {
        return _whiteAccess[user];
    } 

    function userWhiteMints(address user) external view returns(uint256 mints) {
        return _userWhiteMints[user];
    }
    
    //Moderator Functions======================================================================================================================================================

    function setWhiteList(address[] calldata whiteUsers) external Owner {
        uint256 size = whiteUsers.length;
            
            for(uint256 t; t < size; ++t) {
                _whiteAccess[whiteUsers[t]] = true;
            }
    }

    function adminMint(address to, uint256 amount) external Manager {
        _mint(to, amount);
    }

    function adminMint(address[] calldata to, uint256[] calldata amount) external Manager {
        uint256 size = to.length;

        for(uint256 t; t < size; ++t) {
            _mint(to[t], amount[t]);
        }
    }

    function changePrices(uint256 whitePrice, uint256 publicPrice) external Manager {
        _whitePrice = whitePrice;
        _publicPrice = publicPrice;
    }

    function toggleReveal() external Manager {
        _reveal = !_reveal;
    }

    function withdraw(address payable to, uint256 value) external Manager {
        to.transfer(value);
    }

    function distribute() public Manager {
        
        uint256 balance = address(this).balance / 10000; // This is 0.01% of the total balance -> Needed to do presition calculations without floating point.
        
        require(payable(0x81cc8A4bb62fF93f62EC94e3AA40A3A862c54368).send(balance * 5000));
        require(payable(0x10f3667970FAd7dA441261c80727caCd8B164806).send(balance * 900));
        require(payable(0x7A6c41c001d6Fbf4AE6022E936B24d0d39AE3a25).send(balance * 325));
        require(payable(0x6Ec4EAA315aba37B7558A66c51D0dd4986128bCb).send(balance * 325));
        require(payable(0xcc2ba3C4E74A531635b928D2aC5B3f176C8B6ec3).send(balance * 216));
        require(payable(0x37B8C37EB031312c5DaaA02fD5baD9Dc380a8cc4).send(balance * 125));
        require(payable(0xC970bd4E2dF5F33ea62c72b9c3d808b8a609e5e1).send(balance * 550));
        require(payable(0xED7AdfDBbcB1b5C93fa8B6b28B0Fc833Fa68BCA0).send(balance * 580));
        require(payable(0x50a583Ab2432BF3bC5E7458C8ed10BC5Ec3AB23E).send(balance * 580));
        require(payable(0x3b0f95D44f629e8E24a294799c4A1D21f06B6969).send(balance * 225));
        require(payable(0x02916D0f68a02c502476DC630628B01Ee36A7826).send(balance * 50));
        require(payable(0x41b6cb632F5707bF80a1c904316b19fcBee2a4cF).send(balance * 50));
        require(payable(0x2C1Ba2909A0dC98A6219079FBe9A4ab23517D47E).send(balance * 50));
        require(payable(0x58EE6F81AE4Ed77E8Dc50344Ab7571EA7A75a9b7).send(balance * 24));

        require(payable(0x3AA599FB8003B94666c9D66Db43D859ef5EEa29f).send(address(this).balance));
    }
    
    //User Functions======================================================================================================================================================

    function whiteMint() external payable {
        require(_whiteAccess[msg.sender], "SURREAL: Invalid Access"); 

        uint256 amount = msg.value / _whitePrice;

        _userWhiteMints[msg.sender] += amount;
        require(_userWhiteMints[msg.sender] < 11, "SURREAL: Minting Limit Reached");

        _whiteMinted += amount;
        require(_whiteMinted < 1500,"SURREAL: Insufficient White Mint Tokens");

        _mint(msg.sender, amount);
    }

    function mint() external payable {
        uint256 amount = msg.value / _publicPrice;

        require(_totalSupply + amount < 5000, "SURREAL: Insufficient Tokens");

        _mint(msg.sender, amount);
    }

}
function tokenURI(uint256 tokenId) external view override returns (string memory) {
    if(!_reveal) {return string(abi.encodePacked(uriLink, "secret.json"));}
        
    ++tokenId;
    return string(abi.encodePacked(uriLink, tokenId.toString(), ".json"));

}

//Read Functions======================================================================================================================================================