// Retrieve the image specified for this item in its metadata.
        internal IEnumerator GetImage(Action <ImageInfo> listener)
        {
            // First retrieve basic metadata if we have not done so for this item.
            if (this.metadata == null)
            {
                Debug.Log("Retrieving metadata first");

                this.GetMetadata((metadataInfo) =>
                {
                    if (metadataInfo.state == MetadataInfo.MetadataRequestState.SUCCESS)
                    {
                        this.metadata = metadataInfo.metadata;
                        GetImageHelper(listener);
                    }

                    // Trigger our callback with a notice about bad metadata.
                    else
                    {
                        ImageInfo response = new ImageInfo
                        {
                            state     = ImageInfo.ImageRequestState.BAD_METADATA,
                            exception = new ImageRetrievalException()
                        };
                        listener(response);
                    }
                });
            }
            else
            {
                // Prepare a response object.
                ImageInfo response = new ImageInfo();

                // Retrieve the item's image.
                string          imageURI     = this.metadata.image;
                UnityWebRequest imageRequest = UnityWebRequestTexture.GetTexture(imageURI);
                yield return(imageRequest.SendWebRequest());

                // If the request failed, log an error and throw an exception.
                if (imageRequest.isNetworkError || imageRequest.isHttpError)
                {
                    Debug.Log("<color=red>[ERROR]</color> Image network error: " + imageRequest.error);
                    response.state     = ImageInfo.ImageRequestState.RETRIEVAL_FAILED;
                    response.exception = new ImageRetrievalException();
                }

                // Otherwise the request succeeded, so attempt to parse and return.
                else
                {
                    Texture2D texture = DownloadHandlerTexture.GetContent(imageRequest);
                    response.state = ImageInfo.ImageRequestState.SUCCESS;
                    response.image = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height),
                                                   new Vector2(0, 0));
                }

                // Trigger our callback.
                listener(response);
            }
        }
        // Retrieve the basic metadata object required for all items.
        internal IEnumerator GetMetadata(Action <MetadataInfo> listener)
        {
            // Prepare the response object for the callback.
            MetadataInfo response = new MetadataInfo();

            // Issue the web request to fetch the metadata JSON at the item URI.
            UnityWebRequest metadataRequest = UnityWebRequest.Get(itemURI);

            yield return(metadataRequest.SendWebRequest());

            // If the request failed, log an error and throw an exception.
            if (metadataRequest.isNetworkError)
            {
                Debug.Log("<color=red>[ERROR]</color> Metadata network error: " + metadataRequest.error);
                response.state     = MetadataInfo.MetadataRequestState.RETRIEVAL_FAILED;
                response.exception = new MetadataRetrievalException();
            }

            // Otherwise the request succeeded, so attempt to parse and return.
            else
            {
                string metadataString = metadataRequest.downloadHandler.text;

                try
                {
                    this.metadata     = JsonUtility.FromJson <MetadataBase>(metadataString);
                    response.state    = MetadataInfo.MetadataRequestState.SUCCESS;
                    response.metadata = this.metadata;
                }
                catch (Exception e)
                {
                    Debug.Log("<color=red>[ERROR]</color> Failed to parse metadata: " + metadataString);
                    response.state     = MetadataInfo.MetadataRequestState.PARSE_FAILED;
                    response.exception = new MetadataParseException(e);
                }
            }

            // Trigger our callback.
            listener(response);
        }