/// <summary>
        /// High level method that posts a Post to Medium including uploading of
        /// images.
        /// </summary>
        /// <param name="post">An instance of the post to post to the server</param>
        /// <param name="publicationId">Publication/Blog id</param>
        /// <param name="documentBasePath">Base path for images to find relatively pathed images</param>
        /// <returns></returns>
        public MediumPost PublishCompletePost(Post post,
                                              string documentBasePath = null,
                                              bool sendasDraft        = false)
        {
            var mediumPost = new MediumPost
            {
                title         = post.Title,
                content       = post.Body,
                contentFormat = "html",
                publishStatus = sendasDraft ? "draft" : "public",
                tags          = post.Tags
            };

            if (!GetUser())
            {
                return(null);
            }

            if (!PublishPostImages(mediumPost, documentBasePath))
            {
                return(null);
            }

            return(PublishPost(mediumPost, WeblogInfo.BlogId.ToString()));
        }
        /// <summary>
        /// Returns the Image Url from the Post operation
        /// </summary>
        /// <param name="post"></param>
        /// <param name="userId"></param>
        /// <returns></returns>
        public MediumPost PublishPost(MediumPost post, string publicationId = null)
        {
            if (string.IsNullOrEmpty(UserId))
            {
                ErrorMessage = "UserId has not been set yet. Make sure to call GetUser first.";
                return(null);
            }

            var settings = new JsonSerializerSettings()
            {
                NullValueHandling = NullValueHandling.Ignore,
                Formatting        = Formatting.Indented
            };
            var json = JsonConvert.SerializeObject(post, settings);


            string url = MediumApiUrl + "users/" + UserId + "/posts";

            if (!string.IsNullOrEmpty(publicationId))
            {
                url = MediumApiUrl + "publications/" + publicationId + "/posts";
            }

            var http = CreateHttpClient(url, json);

            var httpResult = http.DownloadString(url);

            if (http.Error)
            {
                ErrorMessage = http.ErrorMessage;
                return(null);
            }
            if (httpResult.Contains("\"errors\":"))
            {
                //{ "errors":[{"message":"Publication does not exist or user not allowed to publish in it","code":2006}]}
                var errorResult = JsonConvert.DeserializeObject <ErrorResult>(httpResult);

                StringBuilder sb = new StringBuilder();
                foreach (var err in errorResult.errors)
                {
                    sb.AppendLine(err.message);
                }

                ErrorMessage = sb.ToString();
                return(null);
            }


            var postResult = JsonConvert.DeserializeObject <MediumPostResult>(httpResult);

            if (postResult.data == null)
            {
                ErrorMessage = "Unable to parse publishing API response.";
                return(null);
            }

            this.PostUrl = postResult.data.url;
            return(postResult.data);
        }
        /// <summary>
        /// Scans the HTML document and uploads any local files to the Medium
        /// API and returns URL that are embedded as http links into the document
        /// </summary>
        /// <param name="post"></param>
        /// <param name="basePath"></param>
        /// <returns></returns>
        bool PublishPostImages(MediumPost post, string basePath)
        {
            // base folder name for uploads - just the folder name of the image
            var baseName = Path.GetFileName(basePath);

            baseName = FileUtils.SafeFilename(baseName).Replace(" ", "-");

            var doc = new HtmlDocument();

            doc.LoadHtml(post.content);
            try
            {
                // send up normalized path images as separate media items
                var images = doc.DocumentNode.SelectNodes("//img");
                if (images != null)
                {
                    foreach (HtmlNode img in images)
                    {
                        string imgFile = img.Attributes["src"]?.Value as string;
                        if (imgFile == null)
                        {
                            continue;
                        }

                        if (!imgFile.StartsWith("http://") && !imgFile.StartsWith("https://"))
                        {
                            if (!imgFile.Contains(":\\"))
                            {
                                imgFile = Path.Combine(basePath, imgFile.Replace("/", "\\"));
                            }

                            if (File.Exists(imgFile))
                            {
                                var imgUrl = PublishImage(imgFile);
                                img.Attributes["src"].Value = imgUrl;
                            }
                        }
                    }

                    post.content = doc.DocumentNode.OuterHtml;
                }
            }
            catch (Exception ex)
            {
                ErrorMessage = "Error posting images to Medium: " + ex.Message;
                return(false);
            }

            return(true);
        }