contract Suitcase is ERC721Enumerable, AccessControl {
    using SafeMath for uint256;
    using Counters for Counters.Counter;

    uint256 public maxSupply;
    Counters.Counter private _tokenIdCounter;

    string public contractURI;

    // Mapping from token ID to tokenURI
    mapping(uint256 => string) private _tokenURIs;

    bytes32 public constant ADMIN_ROLE = keccak256("ADMIN");

    bytes32 public constant MINTER_ROLE = keccak256("MINTER");

    bytes32 public constant BURNER_ROLE = keccak256("BURNER");

    bytes32 public constant ARTIST_ROLE = keccak256("ARTIST");

    constructor(uint256 _maxSupply, string memory _contractURI) ERC721("aStable Suitcase", "SUITCASE") {
        require(_maxSupply > 0, "Suitcase: max supply should be greater than zero");
        require(bytes(_contractURI).length > 0, "Suitcase: Cannot set empty contractURI");

        maxSupply = _maxSupply;
        contractURI = _contractURI;
        _setupRole(ADMIN_ROLE, msg.sender);
        _setupRole(MINTER_ROLE, msg.sender);
        _setupRole(BURNER_ROLE, msg.sender);
        _setupRole(ARTIST_ROLE, msg.sender);
        _setRoleAdmin(MINTER_ROLE, ADMIN_ROLE);
        _setRoleAdmin(BURNER_ROLE, ADMIN_ROLE);
        _setRoleAdmin(ARTIST_ROLE, ADMIN_ROLE);
        _setRoleAdmin(ADMIN_ROLE, ADMIN_ROLE);
    }

    modifier onlyMinter() {
        require(hasRole(MINTER_ROLE, msg.sender), "Suitcase: only minter");
        _;
    }

    modifier onlyBurner() {
        require(hasRole(BURNER_ROLE, msg.sender), "Suitcase: only burner");
        _;
    }

    modifier onlyArtist() {
        require(hasRole(ARTIST_ROLE, msg.sender), "Suitcase: only artist");
        _;
    }

    /**
     * Mints Suitcase
     */
    function mint(string memory _tokenURI) public onlyMinter returns (uint256) {
        require(totalSupply() < maxSupply, "Suitcase: Purchase would exceed max supply");
        require(bytes(_tokenURI).length > 0, "Suitcase: Cannot set empty tokenURI");

        uint256 tokenId = _tokenIdCounter.current();
        _safeMint(msg.sender, tokenId);
        _tokenURIs[tokenId] = _tokenURI;
        _tokenIdCounter.increment();
        return tokenId;
    }

    /**
     * Burns Suitcase
     */
    function burn(uint256 tokenId) public onlyBurner {
        _burn(tokenId);
        delete _tokenURIs[tokenId];
    }

    function updateContractURI(string memory _contractURI) public onlyArtist {
        require(bytes(_contractURI).length > 0, "Suitcase: Cannot set empty contractURI");
        contractURI = _contractURI;
    }

    function updateTokenURI(uint256 _tokenId, string memory _tokenURI) public onlyArtist {
        require(_exists(_tokenId), "Suitcase: Update URI query for nonexistent token");
        require(bytes(_tokenURI).length > 0, "Suitcase: Cannot set empty tokenURI");

        _tokenURIs[_tokenId] = _tokenURI;
    }

    function tokenURI(uint256 tokenId) public view override returns (string memory) {
        require(_exists(tokenId), "Suitcase: URI query for nonexistent token");
        return _tokenURIs[tokenId];
    }

    function supportsInterface(bytes4 interfaceId) public view override(ERC721Enumerable, AccessControl) returns (bool) {
        return interfaceId == type(IERC721Enumerable).interfaceId || interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
    }
}
function mint(string memory _tokenURI) public onlyMinter returns (uint256) {
    require(totalSupply() < maxSupply, "Suitcase: Purchase would exceed max supply");
    require(bytes(_tokenURI).length > 0, "Suitcase: Cannot set empty tokenURI");

    uint256 tokenId = _tokenIdCounter.current();
    _safeMint(msg.sender, tokenId);
    _tokenURIs[tokenId] = _tokenURI;
    _tokenIdCounter.increment();
    return tokenId;
}

/**
 * Mints Suitcase
 */