//------------------------------------------------------------------------------
// <copyright company="Telligent Systems">
//     Copyright (c) Telligent Systems Corporation.  All rights reserved.
// </copyright> 
//------------------------------------------------------------------------------

using System;
using System.Collections.Specialized;
using System.IO;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using CommunityServer.Components;

namespace CommunityServer.Galleries.Components
{
    /// <summary>
    /// Summary description for TrackBackNotificationProxy.
    /// </summary>
    public class TrackBackNotificationProxy
    {
        string referral, body;
        byte[] payload = null;

        /// <summary>
        /// Creates a new instance of TrackBackNotificationProxy setting the values needed to complete all the trackbacks
        /// </summary>
        public TrackBackNotificationProxy(string body, string title, string link, string blogname, string description)
        {
            this.referral = link;
            this.body = body;
            string parameters = "title=" + Globals.UrlEncode(title) + "&url=" + Globals.UrlEncode(link) + "&blog_name=" + Globals.UrlEncode(blogname) + "&excerpt=" + Globals.UrlEncode(description);
            payload = Encoding.UTF8.GetBytes(parameters);
        }


        /// <summary>
        /// Creates a new instance of TrackBackNotificationProxy and determines if the trackbacks should happen on a second thread
        /// (Managed ThreadPool)
        /// </summary>
        public static void Track(GalleryPost entry, bool backGroundThread)
        {
            Gallery g = entry.Section as Gallery;
            if(g != null && g.ValidateTrackBacks(entry))
            {
                string desc = entry.HasExcerpt ? entry.Excerpt : CreateDescription(entry.FormattedBody); 
                TrackBackNotificationProxy tbnp = new TrackBackNotificationProxy(entry.FormattedBody,entry.Subject,Globals.FullPath(GalleryUrls.Instance().ViewPicture(g.ApplicationKey, entry) ),g.Name,desc);

                if(backGroundThread)
                    ManagedThreadPool.QueueUserWorkItem(new WaitCallback(tbnp.Track));
                else
                    tbnp.Track();
            }

        }


        /// <summary>
        /// Simply calls this.Track();
        /// </summary>
        public void Track(object state)
        {
            Track();
        }

        /// <summary>
        /// Creates an array of links based on the post's body. Then walks through each link and attempts
        /// to "TrackBack"
        /// </summary>
        public void Track()
        {
        	StringCollection links = GetLinks(body);
            foreach(string externalUrl in links)
            {
                try
                {
                    
                    string pageText = CSRequest.GetPageText(externalUrl,referral);
                    if(pageText != null)
                        TryToPing(pageText,externalUrl);
                }
                catch{}//nothing to do here.
            }

        }

        /// <summary>
        /// Attempts to make a Trackback ping to the supplied Url. The page is requested and then search for trackback links
        /// </summary>
        /// <param name="pageText">Full Text (HTML) of the page to search</param>
        /// <param name="externalUrl">Url to ping</param>
        /// <returns></returns>
        public bool TryToPing(string pageText,string externalUrl)
        {
            string trackBackItem = GetTrackBackText(pageText,externalUrl,referral);
            if(trackBackItem != null)
            {
				if (!trackBackItem.ToLower().StartsWith("http://") && !trackBackItem.ToLower().StartsWith("https://"))
                    trackBackItem = "http://" + trackBackItem;

            	SendPing(trackBackItem);
                return true;
            }
            return false;
			
 
        }

        /// <summary>
        /// If the current site/link supports a trackbacks, we will ping the site here
        /// </summary>
        /// <param name="trackBackItem"></param>
        protected virtual void SendPing(string trackBackItem)
        {

        	HttpWebRequest request = CSRequest.CreateRequest(trackBackItem,referral);
            request.Method = "POST";
            request.ContentLength = payload.Length;
            request.ContentType = "application/x-www-form-urlencoded";
            request.KeepAlive = false;

            using(Stream st = request.GetRequestStream())
            {
                st.Write(payload, 0, payload.Length);
                st.Close();

                using(WebResponse response = request.GetResponse())
                {
                    response.Close();
                }
            }
        }

        #region Helpers


        private static string CreateDescription(string text)
        {
            text = StripHtmlXmlTags(text);
            if (text.Trim().Length > 100)
            {
                int place = 100;
                int len = text.Length - 1;
                while (!Char.IsWhiteSpace(text[place]) && place < len)
                {
                    place++;
                }
                text =  string.Format("{0}...", text.Substring(0, place));
            }
            return text;

        }

        public static string StripHtmlXmlTags(string content)
        {
            return Regex.Replace(content, "<[^>]+>", "", RegexOptions.IgnoreCase | RegexOptions.Compiled);
        }

 
        private static string GetTrackBackText(string pageText, string url, string PostUrl)
        {
            if(!Regex.IsMatch(pageText,PostUrl,RegexOptions.IgnoreCase|RegexOptions.Singleline))
            {

                string sPattern = @"<rdf:\w+\s[^>]*?>(</rdf:rdf>)?";
                Regex r = new Regex(sPattern,RegexOptions.IgnoreCase);
                Match m;
			
                for (m = r.Match(pageText); m.Success; m = m.NextMatch()) 
                {
                    if(m.Groups.ToString().Length > 0)
                    {
					
                        string text = m.Groups[0].ToString();
                        if(text.IndexOf(url) > 0)
                        {
                            string tbPattern = "trackback:ping=\"([^\"]+)\"";
                            Regex reg = new Regex(tbPattern, RegexOptions.IgnoreCase);
                            Match m2 = reg.Match(text) ;
                            if ( m2.Success )
                            {
                                return m2.Result("$1") ;
                            }


                            return text;
                        }
                    }
                }
            }

            return null;	
        }

        /// <summary>
        /// Gets a list of all of the valid html links from a string
        /// </summary>
        /// <param name="text"></param>
        /// <returns></returns>
        public static StringCollection GetLinks(string text)
        {			
            StringCollection links = new StringCollection();
            string sPattern = @"(?:[hH][rR][eE][fF]\s*=)" +
                @"(?:[\s""']*)(?!#|[Mm]ailto|[lL]ocation.|[jJ]avascript|.*css|.*this\.)" +
                @"(.*?)(?:[\s>""'])";

            Regex r = new Regex(sPattern,RegexOptions.IgnoreCase);
            Match m;
            string link = null;
            for (m = r.Match(text); m.Success; m = m.NextMatch()) 
            {
				
                if(m.Groups.ToString().Length > 0 )
                {
					
                    link = 	m.Groups[1].ToString();	
                    if(!links.Contains(link))
                    {
                        links.Add(link);
                    }
                }
            }
            return links;	
        }

        #endregion
    }
}

