contract OutLawPunk is ERC721, Ownable {
  using SafeMath for uint256;

  uint256 public constant MAX_SUPPLY = 10000;
  uint256 public constant price = 0.05 *10**18;
  uint public constant maxTokenPurchase = 20;
  uint public reservedTokens = 20;
  bool public saleIsActive = false;

  mapping (address => uint) public usersMintedTokens;

  constructor(string memory tokenName, string memory symbol) ERC721(tokenName, symbol) { }
  

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


  function mintToken(uint numberOfTokens) public payable {
    require(saleIsActive, "Sale not active yet.");
    require(numberOfTokens > 0, "Number of tokens should be greater than 0");
    require(numberOfTokens <= maxTokenPurchase, "Can only mint 20 tokens per transaction");
    require(totalSupply().add(numberOfTokens) <= MAX_SUPPLY, "Purchase would exceed max supply");
    require(price.mul(numberOfTokens) <= msg.value, "ETH value sent is not correct");

    // to track minted tokens per address
    usersMintedTokens[msg.sender] = usersMintedTokens[msg.sender].add(numberOfTokens);


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


  function giveaway(address[] calldata arUsers) external onlyOwner {
    require(arUsers.length <= reservedTokens, 'Request will exceed total reserved supply.');

    for (uint i = 0; i < arUsers.length; i++) {
      uint mintIndex = totalSupply();

      if (totalSupply() < MAX_SUPPLY) {
        _safeMint(arUsers[i], mintIndex);
      }
    }

    reservedTokens = reservedTokens.sub(arUsers.length);
  }


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

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

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