contract ChainRenegades is ERC721Enumerable, Ownable {
  using Strings for uint256;

  // Override Base Token URI Variable
  string public _baseTokenURI;

  // Drop Details
  bool public _active = false;
  uint256 public _gifts = 600;
  uint256 public _price = 0.055 ether;
  uint256 public _supply = 9999;

  // Team Addresses
  address public artist = 0x8b88130e3B6d99aC05e382C17bD28dcaD2F86D41;
  address public dev = 0xd230f390AbB50470fa265a022d673c6147BDc396;

  // On deployment, set the `baseURI` and mint the team tokens
  constructor(string memory baseURI) ERC721("Chain Renegades", "CR") {
    setBaseURI(baseURI);
    _safeMint( artist, 0);
    _safeMint( dev, 1);
  }

  /*
  * @dev: Override function for `_baseURI()` that returns `_baseTokenURI`
  */
  function _baseURI() internal view virtual override returns (string memory) {
    return _baseTokenURI;
  }

  /*
  * @dev: Sets `_baseTokenURI` to provided string
  */
  function setBaseURI(string memory baseURI) public onlyOwner {
    _baseTokenURI = baseURI;
  }

  /*
  * @dev: Sets `_active` to provided boolean value
  */
  function setActive(bool active) public onlyOwner {
     _active = active;
  }

  /*
  * @dev: Returns tokens in the wallet of the provided `_owner`
  */
  function getTokensByWallet(address _owner) public view returns(uint256[] memory) {
    uint256 tokenCount = balanceOf(_owner);

    uint256[] memory tokensId = new uint256[](tokenCount);
    for(uint256 i; i < tokenCount; i++){
        tokensId[i] = tokenOfOwnerByIndex(_owner, i);
    }
    return tokensId;
  }

  /*
  * @dev: Sends provided token `_amount` to the provided address
  */
  function gift(address _to, uint256 _amount) external onlyOwner {
    // Check that the amount provided does not exceed the gift reserve
    require(_amount <= _gifts, "Gift reserve exceeded with provided amount.");

    uint256 supply = totalSupply();

    for(uint256 i; i < _amount; i++){
      _safeMint( _to, supply + i );
    }

    _gifts -= _amount;
  }

  /*
  * @dev: Mints the provided token `_amount`
  */
  function train(uint256 _amount) public payable {
    uint256 supply = totalSupply();

    // Check that the sale is active
    require( _active, "Sale is not active.");

    // Check that provided amount does not exceed limit
    require( _amount < 21, "Provided amount exceeds mint limit.");

    // Check that the provided ether is sufficient
    require( msg.value >= _price * _amount, "Insufficient ether provided.");

    // Check that amount provided does not exceed the supply
    require( supply + _amount <= _supply - _gifts, "Supply exceeded with provided amount.");

    for(uint256 i; i < _amount; i++){
      _safeMint( msg.sender, supply + i );
    }
  }

  /*
  * @dev: Splits contract balance and sends half to the artist & half to the dev
  */
  function withdraw() public payable onlyOwner {
    uint256 _each = address(this).balance / 2;

    require(payable(artist).send(_each));
    require(payable(dev).send(_each));
  }
}
// OpenZeppelin Imports
// Chain Renegades | ERC721 \ Ownable
function setBaseURI(string memory baseURI) public onlyOwner {
  _baseTokenURI = baseURI;
}

/*
 * @dev: Sets `_baseTokenURI` to provided string
 */