contract AstroRookies is ERC721, Ownable {
    
    using SafeMath for uint256;
    // sale is not opened when contract deployed to etherscan
    // we will open it at sale day.
    bool public saleIsActive = false;
    // Provenance hash for 10.000 images.
    string public PROVENANCE_HASH = "bcd97e4d47cdbc7dae09cda03462e9d2d28dd99884f1002e9277158bd800321d"; 
    // One rookie price : 0.05 ETH
    uint public constant ROOKIE_PRICE = 50000000000000000;
    // There are 10.000 rookies only.
    uint public constant MAX_ROOKIE_SUPPLY = 10000;
    // You can only mint 30 rookie at one transaction.
    uint public constant MAX_PURCHASE_PER_TX = 30;
    // Reserve 100 Rookies for team, giveaways and contests.
    uint public RESERVE_ROOKIE = 100;

    constructor() ERC721("AstroRookies", "RoRoo") { }
    

    function withdrawAll() public onlyOwner {
        uint balance = address(this).balance;
        msg.sender.transfer(balance);
    }

    /**
    @notice Only owner can use this function. With that function owner can send
            nft to any address without paying price but gas.
     */
    function reserveRookies(address _to, uint256 _reserveAmount) public onlyOwner {        
        uint supply = totalSupply();
        require(_reserveAmount > 0 && _reserveAmount <= RESERVE_ROOKIE, "Not enough reserve left for team");
        for (uint i = 0; i < _reserveAmount; i++) {
            _safeMint(_to, supply + i);
        }
        // Reserve rookies now equals to this : RESERVE_ROOKIE - _reserveAmount.
        // We're using sub function because we want to do it safely with SafeMath.
        RESERVE_ROOKIE = RESERVE_ROOKIE.sub(_reserveAmount);
    }

    /**
    @notice This functions works under some conditions. First of all sale has to be started.
            Then it checks for the amount of nft tried to minted. If user requests less than 1 or 
            greater than 30 it wont work. Then it checks for max supply and lastly it checks for
            price that sended for nft amount that wanted to be minted.  If all of them OK then minting
            starts.
     */
    function mintRookies(uint numberOfTokens) public payable {
        require(saleIsActive, "Sale must be active to mint");
        require(numberOfTokens > 0 && numberOfTokens <= MAX_PURCHASE_PER_TX, "Can only mint 30 tokens at a time");
        require(totalSupply().add(numberOfTokens) <= MAX_ROOKIE_SUPPLY, "Purchase would exceed max supply of nft");
        require(msg.value >= ROOKIE_PRICE.mul(numberOfTokens), "Ether value sent is not correct");
        // check
        for(uint i = 0; i < numberOfTokens; i++) {
            uint mintIndex = totalSupply();
            if (totalSupply() < MAX_ROOKIE_SUPPLY) {
                _safeMint(msg.sender, mintIndex);
            }
        }
    }

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

    function flipSaleState() public onlyOwner {
        saleIsActive = !saleIsActive;
    }

    function tokensOfOwner(address _owner) external view returns(uint256[] memory ) {
        uint256 tokenCount = balanceOf(_owner);
        if (tokenCount == 0) {
            // Return an empty array
            return new uint256[](0);
        } else {
            uint256[] memory result = new uint256[](tokenCount);
            uint256 index;
            for (index = 0; index < tokenCount; index++) {
                result[index] = tokenOfOwnerByIndex(_owner, index);
            }
            return result;
        }
    }
    
}
/**
 @title      Astro Rookies Contract
 @author     Team: Battori - RobScalera - Root - RTA - VaCancY - Wrooya
 */
function reserveRookies(address _to, uint256 _reserveAmount) public onlyOwner {        
    uint supply = totalSupply();
    require(_reserveAmount > 0 && _reserveAmount <= RESERVE_ROOKIE, "Not enough reserve left for team");
    for (uint i = 0; i < _reserveAmount; i++) {
        _safeMint(_to, supply + i);
    }
    // Reserve rookies now equals to this : RESERVE_ROOKIE - _reserveAmount.
    // We're using sub function because we want to do it safely with SafeMath.
    RESERVE_ROOKIE = RESERVE_ROOKIE.sub(_reserveAmount);
}

/**
 @notice Only owner can use this function. With that function owner can send
 nft to any address without paying price but gas.
 */