contract Origins is ERC721Burnable, Ownable {
    uint256 constant public PRICE = 0.05 ether;
    uint256 constant public TOTAL_SUPPLY = 8000;
    uint256 constant public REVEAL_TIMESTAMP = 0;
    uint256 constant public MAX_PER_TX = 30;

    uint256 public startingIndex;
    uint256 public startingIndexBlock;

    string constant public METADATA_HASH = "";
    
    address payable claimEthAddress;

    bool private saleIsActive;

    constructor(address payable _claimEthAddress) public ERC721("Origins", "Origin") {
        claimEthAddress = _claimEthAddress;
    }

    function reserveOrigins(address addr, uint256 amount) public onlyOwner {
        uint supply = totalSupply();
        uint i;
        for (i = 0; i < amount; i++) {
            _safeMint(addr, supply + i);
        }
    }

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

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

    /**
    * Mint Origins
    */
    function mintOrigins(uint numberOfTokens) public payable {
        require(saleIsActive, "Sale must be active to mint");
        require(numberOfTokens <= MAX_PER_TX, "Above max tx count");
        require(totalSupply().add(numberOfTokens) <= TOTAL_SUPPLY, "Exceeds max supply");
        require(PRICE.mul(numberOfTokens) <= msg.value, "ETH sent is incorrect");
        for(uint i = 0; i < numberOfTokens; i++) {
            uint mintIndex = totalSupply();
            _safeMint(msg.sender, mintIndex);
        }
            
        // If we haven't set the starting index and this is either
        // 1) the last saleable token or
        // 2) the first token to be sold after the end of pre-sale, set the starting index block
        if (startingIndexBlock == 0 && (totalSupply() == TOTAL_SUPPLY || block.timestamp >= REVEAL_TIMESTAMP)) {
            startingIndexBlock = block.number;
        }
    }

    /**
    * Set the starting index for the collection
    */
    function setStartingIndex() public {
        require(startingIndex == 0, "Starting index is already set");
        require(startingIndexBlock != 0, "Starting index block must be set");
        startingIndex = uint(blockhash(startingIndexBlock)) % TOTAL_SUPPLY;
        // Just a sanity case in the worst case if this function is called late (EVM only stores last 256 block hashes)
        if (block.number.sub(startingIndexBlock) > 255) {
            startingIndex = uint(blockhash(block.number - 1)) % TOTAL_SUPPLY;
        }
    }

    function claimETH() public {
        require(claimEthAddress == _msgSender(), "Ownable: caller is not the claimEthAddress");
        payable(address(claimEthAddress)).transfer(address(this).balance);
    }

    function tokenURI(uint256 tokenId) public view override returns (string memory) {
        if (startingIndex == 0) {
            return super.tokenURI(0);
        }
        uint256 moddedId = (tokenId + startingIndex) % TOTAL_SUPPLY;
        return super.tokenURI(moddedId);
    }
}
function setStartingIndex() public {
    require(startingIndex == 0, "Starting index is already set");
    require(startingIndexBlock != 0, "Starting index block must be set");
    startingIndex = uint(blockhash(startingIndexBlock)) % TOTAL_SUPPLY;
    // Just a sanity case in the worst case if this function is called late (EVM only stores last 256 block hashes)
    if (block.number.sub(startingIndexBlock) > 255) {
        startingIndex = uint(blockhash(block.number - 1)) % TOTAL_SUPPLY;
    }
}

/**
 * Set the starting index for the collection
 */