contract NFTFactory {
    // address of creator => NFT contract address
    mapping(address => NFT[]) nftMap;
    // number of NFTs issued from factory
    uint256 public nftCount;
    // return addresses of deployed NFTs
    NFT[] public nfts;
    // emits when new NFT issued
    event CreateNFT(address indexed newNFT);
    
    /**
     * @dev Creates a new NFT.
     * @param owner Base account (owner[0]) starts with admin and minter role; others, NFT grants.
     * @param name The name of NFT.
     * @param symbol The symbol of NFT.
     * @param baseURI The base URI metadata for NFT.
     * @param tokenId The `tokenId` for initial NFT minted to owner(s). 
     * @param tokenURI The `tokenURI` for initial NFT minted to owner(s). 
     * 
     * Requirements:
     *
     * - array lengths must match.
     */
    function createNFT(
        address[] calldata owner, 
        string calldata name, 
        string calldata symbol, 
        string calldata baseURI, 
        uint256[] calldata tokenId, 
        string[] calldata tokenURI
    ) external {
        require(owner.length == tokenId.length && owner.length == tokenURI.length, "!owner/tokenId/tokenURI");
        // new NFT
        NFT nft = new NFT(
            owner, 
            name,
            symbol,
            baseURI,
            tokenId,
            tokenURI);
            
        // push into mapping of NFTs by base owner (owner[0])
        nftMap[owner[0]].push(nft);
        // push into array to get NFTs in order
        nfts.push(nft);
        // increment NFT count
        nftCount++;

        emit CreateNFT(address(nft));
    }

    /**
     * @dev owner is the base owner of the NFT. 
     */
    function getNFTByAddress(address owner) external view returns (NFT[] memory) {
        return nftMap[owner];
    }
}
/**
 * @dev {ERC721} token factory ("NFTFactory"), including:
 *  
 *  - ability for holders to burn (destroy) their tokens
 *  - an admin role that allows for role management
 *  - a minter role that allows for token minting (creation)
 */
function getNFTByAddress(address owner) external view returns (NFT[] memory) {
        return nftMap[owner];
    }
/**
 * @dev owner is the base owner of the NFT. 
 */