contract UnitedPunksUnion is ERC721, Ownable {
    
    using SafeMath for uint256;
    uint public constant MAX_UNITEDPUNKSUNION = 13666;
    bool public hasSaleStarted = true;
    uint public constant UNITEDPUNKSUNION_PRICE = 30000000000000000;

    string public METADATA_PROVENANCE_HASH = "";
    
    constructor() ERC721("UnitedPunksUnion","UPU")  { }
    
    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;
        }
    }
    
   function buy(uint256 numPunks) public payable {
        require(totalSupply() < MAX_UNITEDPUNKSUNION, "Sale has already ended");
        require(numPunks > 0 && numPunks <= 20, "You can adopt minimum 1, maximum 20 United Union Punks");
        require(totalSupply().add(numPunks) <= MAX_UNITEDPUNKSUNION, "Exceeds MAX_UNITEDPUNKSUNION");
        require(msg.value >= UNITEDPUNKSUNION_PRICE.mul(numPunks), "Ether value sent is below the price");

        for (uint i = 0; i < numPunks; i++) {
            uint mintIndex = totalSupply();
            _safeMint(msg.sender, mintIndex);
        }

    }
        function getPrice(uint _count) public view returns (uint256) {
        uint256 returnVal = 0;
        if(totalSupply() <= MAX_UNITEDPUNKSUNION ){
           returnVal = UNITEDPUNKSUNION_PRICE * _count; // 0.03 ETH
        }

        return returnVal;
    }

    // ONLYOWNER FUNCTIONS
    
    function setProvenanceHash(string memory _hash) public onlyOwner {
        METADATA_PROVENANCE_HASH = _hash;
    }
    
function giveGift(address _address, uint numPunks) public onlyOwner {
        uint mintIndex = totalSupply();
        require(mintIndex < 240);
        require(totalSupply().add(numPunks) <= 240, "Exceeds MAX_UNITEDPUNKSUNION");
        for (uint i = 0; i < numPunks; i++) {
            _safeMint(_address, mintIndex + i);
        }
    }
    
    function setBaseURI(string memory baseURI) public onlyOwner {
        _setBaseURI(baseURI);
    }
    
    function startDrop() public onlyOwner {
        hasSaleStarted = true;
    }
    
    function pauseDrop() public onlyOwner {
        hasSaleStarted = false;
    }
    
    function withdraw() public payable onlyOwner {
        require(payable(msg.sender).send(address(this).balance));
    }
    
}
function setProvenanceHash(string memory _hash) public onlyOwner {
    METADATA_PROVENANCE_HASH = _hash;
}

// ONLYOWNER FUNCTIONS