///TODO: Include update with html mail notification and document contents
        private static void sendNotification(User performingUser, User mailingUser, Document documentObject,
                                             IAction Action)
        {
            // retrieve previous version of the document
            DocumentVersionList[] versions = documentObject.GetVersions();
            int versionCount = (versions.Length > 1) ? (versions.Length - 2) : (versions.Length - 1);
            var oldDoc = new Document(documentObject.Id, versions[versionCount].Version);

            // build summary
            var summary = new StringBuilder();
            var props = documentObject.GenericProperties;
            foreach (Property p in props)
            {
                // check if something was changed and display the changes otherwise display the fields
                Property oldProperty = oldDoc.getProperty(p.PropertyType.Alias);
                string oldText = oldProperty.Value.ToString();
                string newText = p.Value.ToString();

                // replace html with char equivalent
                ReplaceHTMLSymbols(ref oldText);
                ReplaceHTMLSymbols(ref newText);

                // make sure to only highlight changes done using TinyMCE editor... other changes will be displayed using default summary
                ///TODO PPH: Had to change this, as a reference to the editorcontrols is not allowed, so a string comparison is the only way, this should be a DIFF or something instead.. 
                if (p.PropertyType.DataTypeDefinition.DataType.ToString() ==
                    "umbraco.editorControls.tinymce.TinyMCEDataType" &&
                    string.Compare(oldText, newText) != 0)
                {
                    summary.Append("<tr>");
                    summary.Append("<th style='text-align: left; vertical-align: top; width: 25%;'> Note: </th>");
                    summary.Append(
                        "<td style='text-align: left; vertical-align: top;'> <span style='background-color:red;'>Red for deleted characters</span>&nbsp;<span style='background-color:yellow;'>Yellow for inserted characters</span></td>");
                    summary.Append("</tr>");
                    summary.Append("<tr>");
                    summary.Append("<th style='text-align: left; vertical-align: top; width: 25%;'> New " +
                                   p.PropertyType.Name + "</th>");
                    summary.Append("<td style='text-align: left; vertical-align: top;'>" +
                                   replaceLinks(CompareText(oldText, newText, true, false,
                                                            "<span style='background-color:yellow;'>", string.Empty)) +
                                   "</td>");
                    summary.Append("</tr>");
                    summary.Append("<tr>");
                    summary.Append("<th style='text-align: left; vertical-align: top; width: 25%;'> Old " +
                                   oldProperty.PropertyType.Name + "</th>");
                    summary.Append("<td style='text-align: left; vertical-align: top;'>" +
                                   replaceLinks(CompareText(newText, oldText, true, false,
                                                            "<span style='background-color:red;'>", string.Empty)) +
                                   "</td>");
                    summary.Append("</tr>");
                }
                else
                {
                    summary.Append("<tr>");
                    summary.Append("<th style='text-align: left; vertical-align: top; width: 25%;'>" +
                                   p.PropertyType.Name + "</th>");
                    summary.Append("<td style='text-align: left; vertical-align: top;'>" + p.Value.ToString() + "</td>");
                    summary.Append("</tr>");
                }
                summary.Append(
                    "<tr><td colspan=\"2\" style=\"border-bottom: 1px solid #CCC; font-size: 2px;\">&nbsp;</td></tr>");
            }

            string protocol = GlobalSettings.UseSSL ? "https" : "http";


            string[] subjectVars = {
                                       HttpContext.Current.Request.ServerVariables["SERVER_NAME"] + ":" +
                                       HttpContext.Current.Request.Url.Port +
                                       IOHelper.ResolveUrl(SystemDirectories.Umbraco), ui.Text(Action.Alias)
                                       ,
                                       documentObject.Text
                                   };
            string[] bodyVars = {
                                    mailingUser.Name, ui.Text(Action.Alias), documentObject.Text, performingUser.Name,
                                    HttpContext.Current.Request.ServerVariables["SERVER_NAME"] + ":" +
                                    HttpContext.Current.Request.Url.Port +
                                    IOHelper.ResolveUrl(SystemDirectories.Umbraco),
                                    documentObject.Id.ToString(), summary.ToString(),
                                    String.Format("{2}://{0}/{1}",
                                                  HttpContext.Current.Request.ServerVariables["SERVER_NAME"] + ":" +
                                                  HttpContext.Current.Request.Url.Port,
                                                  /*umbraco.library.NiceUrl(documentObject.Id))*/
                                                  documentObject.Id + ".aspx",
                                                  protocol)
                                    ///TODO: PPH removed the niceURL reference... cms.dll cannot reference the presentation project...
                                    ///TODO: This should be moved somewhere else..
                                };

            // create the mail message 
            var mail = new MailMessage(UmbracoSettings.NotificationEmailSender, mailingUser.Email);

            // populate the message
            mail.Subject = ui.Text("notifications", "mailSubject", subjectVars, mailingUser);
            if (UmbracoSettings.NotificationDisableHtmlEmail)
            {
                mail.IsBodyHtml = false;
                mail.Body = ui.Text("notifications", "mailBody", bodyVars, mailingUser);
            }
            else
            {
                mail.IsBodyHtml = true;
                mail.Body =
                    @"<html><head>
</head>
<body style='font-family: Trebuchet MS, arial, sans-serif; font-color: black;'>
" +
                    ui.Text("notifications", "mailBodyHtml", bodyVars, mailingUser) + "</body></html>";
            }

            // nh, issue 30724. Due to hardcoded http strings in resource files, we need to check for https replacements here
            // adding the server name to make sure we don't replace external links
            if (GlobalSettings.UseSSL && !String.IsNullOrEmpty(mail.Body))
            {
                string serverName = HttpContext.Current.Request.ServerVariables["SERVER_NAME"];
                mail.Body = mail.Body.Replace(
                    string.Format("http://{0}", serverName),
                    string.Format("https://{0}", serverName));
            }

            // send it
            var sender = new SmtpClient();
            sender.Send(mail);
        }
        /// <summary>
        /// Moves a Post if the Post Date Changes
        /// </summary>
        /// <param name="sender">Document Being Published</param>
        /// <param name="e">Publish Event Args</param>
        void Document_BeforePublish(Document sender, umbraco.cms.businesslogic.PublishEventArgs e)
        {
            if (sender.ContentType.Alias == "BlogPost") //As this runs for every publish event, only proceed if this is BlogPost
            {
                Log.Add(LogTypes.Debug, sender.User, sender.Id, string.Format("Start Before Publish Event for Blog Post {0}", sender.Id));
                if (sender.getProperty("PostDate") != null) //If no post date, skip 
                {
                    if (sender.Parent != null)  //If top of tree, something is wrong.  Skip.
                    {
                        try
                        {
                            DocumentVersionList[] postVersions = sender.GetVersions();
                            bool _versionCheck = true;
                            DateTime postDate;
                            postDate = System.Convert.ToDateTime(sender.getProperty("PostDate").Value);
                            if (postVersions.Length > 1)  //If it has been published, check post date info
                            {
                                //Length -1 is current version Length -2 is past version (if it exists)
                                Guid previousVersion = postVersions[postVersions.Length - 2].Version;
                                Document doc = new Document(sender.Id, previousVersion);
                                DateTime previousPostDate = System.Convert.ToDateTime(doc.getProperty("PostDate").Value);

                                _versionCheck = (postDate != previousPostDate);
                            }

                            if (_versionCheck)  //Only do the date folder movement if the PostDate is changed or is new Post.
                            {
                                string[] strArray = { postDate.Year.ToString(), postDate.Month.ToString(), postDate.Day.ToString() };
                                if (strArray.Length == 3)
                                {
                                    Node topBlogLevel = new Node(sender.Parent.Id);
                                    //Traverse up the tree to Find the Blog Node since we are likely in a Date Folder path
                                    while (topBlogLevel != null && topBlogLevel.NodeTypeAlias != "Blog")
                                    {
                                        if (topBlogLevel.Parent != null)
                                        {
                                            topBlogLevel = new Node(topBlogLevel.Parent.Id);
                                        }
                                        else
                                        {
                                            topBlogLevel = null;
                                        }
                                    }
                                    if (topBlogLevel != null)
                                    {
                                        Document document = null;
                                        Node folderNode = null;
                                        foreach (Node ni in topBlogLevel.Children)
                                        {
                                            if (ni.Name == strArray[0])
                                            {
                                                folderNode = new Node(ni.Id);
                                                document = new Document(ni.Id);
                                                break;
                                            }
                                        }
                                        if (folderNode == null)
                                        {
                                            document = Document.MakeNew(strArray[0], DocumentType.GetByAlias("DateFolder"), sender.User, topBlogLevel.Id);
                                            document.Publish(sender.User);
                                            library.UpdateDocumentCache(document.Id);
                                            folderNode = new Node(document.Id);
                                        }
                                        Node folderNode2 = null;
                                        foreach (Node ni in folderNode.Children)
                                        {
                                            if (ni.Name == strArray[1])
                                            {
                                                folderNode2 = new Node(ni.Id);
                                                break;
                                            }
                                        }
                                        if (folderNode2 == null)
                                        {
                                            Document document2 = Document.MakeNew(strArray[1], DocumentType.GetByAlias("DateFolder"), sender.User, folderNode.Id);
                                            document2.Publish(sender.User);
                                            library.UpdateDocumentCache(document2.Id);
                                            folderNode2 = new Node(document2.Id);
                                        }
                                        Document document3 = null;  //As this is the last check, a document object is fine
                                        foreach (Node ni in folderNode2.Children)
                                        {
                                            if (ni.Name == strArray[2])
                                            {
                                                document3 = new Document(ni.Id);
                                                break;
                                            }
                                        }
                                        if (document3 == null)
                                        {
                                            document3 = Document.MakeNew(strArray[2], DocumentType.GetByAlias("DateFolder"), sender.User, folderNode2.Id);
                                            document3.Publish(sender.User);
                                            library.UpdateDocumentCache(document3.Id);
                                        }
                                        if (sender.Parent.Id != document3.Id)
                                        {
                                            sender.Move(document3.Id);
                                            Log.Add(LogTypes.Debug, sender.User, sender.Id, string.Format("Move Required for BlogPost {0} for PostDate {1}.  Moved Under Node {2}", sender.Id, postDate.ToShortDateString(), document3.Id));
                                        }
                                    }
                                    else
                                    {
                                        Log.Add(LogTypes.Debug, sender.User, sender.Id, string.Format("Unable to determine top of Blog for BlogPost {0} while attempting to move to new Post Date", sender.Id));
                                    }

                                }
                            }
                        }
                        catch (Exception Exp)
                        {
                            Log.Add(LogTypes.Debug, sender.User, sender.Id, string.Format("Error while Finding Blog Folders for BlogPost {0} while trying to move to new Post Date.  Error: {1}", sender.Id, Exp.Message));
                        }

                        umbraco.library.RefreshContent();
                    }
                }
            }
        }
        private bool HasDateChanged(Document document)
        {
            DocumentVersionList[] versions = document.GetVersions();
            bool dateHasChanged = true;
            DateTime itemDate = Convert.ToDateTime(document.getProperty(ItemDateProperty).Value);

            if (versions.Length > 1)
            {
                Guid version = versions[versions.Length - 2].Version;
                DateTime oldItemDate = Convert.ToDateTime(new Document(document.Id, version).getProperty(ItemDateProperty).Value);
                dateHasChanged = itemDate != oldItemDate;
            }

            return dateHasChanged;
        }