contract PoiPuppyLei is ERC721, Ownable, ReentrancyGuard {
    bool public isActive;
    uint256 public constant MAX_SUPPLY = 1000;
    uint256 public constant PER_ORDER_LIMIT = 10;

    string public constant BASE_URI =
        "ipfs://QmepuZG5nNNgEjWBNBPJ4DXqsey1smPukU8Ht323DkKn83/";

    using Counters for Counters.Counter;
    Counters.Counter private _tokenIds;

    constructor() ERC721("Poi Puppy Lei", "PPL") {
        isActive = false;
    }

    function mint(uint256 qty) public payable nonReentrant {
        require(isActive, "Contract is not active");
        require(qty <= PER_ORDER_LIMIT, "Cannot purchase more than the per-order limit");
        require((totalSold() + qty) <= MAX_SUPPLY, "Requested quantity would exceed total supply");
        require(msg.value == (salePrice() * qty), "Incorrect payment amount");

        for (uint256 i = 0; i < qty; i++) {
            _tokenIds.increment();
            uint256 mintIndex = totalSold();
            _safeMint(msg.sender, mintIndex);
        }
    }

    function totalSupply() public pure returns (uint256) {
        return MAX_SUPPLY;
    }

    function salePrice() public pure returns (uint256) {
        return 2000000000000000 wei; // 0.0020 ether
    }

    function totalSold() public view returns (uint256) {
        return _tokenIds.current();
    }

    function setActive(bool val) public onlyOwner {
        isActive = val;
    }

    function _baseURI() internal view virtual override returns (string memory) {
        return BASE_URI;
    }

    function tokenURI(uint256 tokenId)
        public
        view
        override
        returns (string memory)
    {
        require(tokenId > 0, "Token Id = 0");

        string memory baseURI = _baseURI();
        return
            bytes(baseURI).length > 0
                ? string(abi.encodePacked(baseURI, uint2str(tokenId), ".json"))
                : "";
    }

    // https://stackoverflow.com/a/47137572
    function uint2str(uint256 _i)
        private
        pure
        returns (string memory _uintAsString)
    {
        if (_i == 0) {
            return "0";
        }
        uint256 j = _i;
        uint256 len;
        while (j != 0) {
            len++;
            j /= 10;
        }
        bytes memory bstr = new bytes(len);
        uint256 k = len;
        while (_i != 0) {
            k = k - 1;
            uint8 temp = (48 + uint8(_i - (_i / 10) * 10));
            bytes1 b1 = bytes1(temp);
            bstr[k] = b1;
            _i /= 10;
        }
        return string(bstr);
    }
}
function uint2str(uint256 _i)
        private
        pure
        returns (string memory _uintAsString)
    {
        if (_i == 0) {
            return "0";
        }
        uint256 j = _i;
        uint256 len;
        while (j != 0) {
            len++;
            j /= 10;
        }
        bytes memory bstr = new bytes(len);
        uint256 k = len;
        while (_i != 0) {
            k = k - 1;
            uint8 temp = (48 + uint8(_i - (_i / 10) * 10));
            bytes1 b1 = bytes1(temp);
            bstr[k] = b1;
            _i /= 10;
        }
        return string(bstr);
    }
// https://stackoverflow.com/a/47137572