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

using System;
using System.Collections;
using System.Text.RegularExpressions;
using System.Web;

namespace CommunityServer.Components
{
	/// <summary>
	/// Summary description for Referrals.
	/// </summary>
	public class Referrals
	{
        /// <summary>
        /// Internal referral container
        /// </summary>
        private static ArrayList referralQueue = new ArrayList();

        /// <summary>
        /// This class can not be instatiated
        /// </summary>
		private Referrals()
		{
			
		}
        
        /// <summary>
        /// Adds a referral directly to the internal Queue
        /// </summary>
        /// <param name="r"></param>
        public static void AddToQueue(Referral r)
        {
            lock(referralQueue.SyncRoot)
            {
                referralQueue.Add(r);
            }
        }

        /// <summary>
        /// First tries to look up a valid referral. If found, the referral will be added to the Queue.
        /// </summary>
        /// <param name="context">Current HttpContext</param>
        /// <param name="filter">General used to make sure a blog,forum,gallery do not track their own referrals</param>
        /// <param name="r">Object container with referral info. The property Referral.Url will be ignored in this method</param>
        public static void AddToQueue(HttpContext context, string filter, Referral r)
        {
			try
			{
				string refUrl = GetReferralUrl(context.Request.UrlReferrer,context.Request.Url,context.Request.UserAgent,filter);
				if(refUrl != null)
				{
					r.Url = refUrl;
					AddToQueue(r);
				}
			}
			catch{} //lets make sure no weirdness with referrals does not leave us hangling

        }

        /// <summary>
        /// Returns a list of Referrals in the current queue and resets the queue back to zero items
        /// </summary>
        public static ArrayList ReQueue()
        {
            ArrayList previousQueue = null;
            lock(referralQueue.SyncRoot)
            {
                previousQueue = new ArrayList(referralQueue);
                referralQueue.Clear();
            }

            return previousQueue;
        }

        #region Data Access
        /// <summary>
        /// Gets the current queued items by calling ReQueue(). It then saves the results to the datastore
        /// </summary>
        public static void SaveQueue()
        {
            ArrayList queue = ReQueue();
            CommonDataProvider dp = CommonDataProvider.Instance();
            dp.SaveReferralList(queue);
        }

        public static ReferralSet GetReferrals(Referral r, int pageSize, int pageIndex)
        {
            CommonDataProvider dp = CommonDataProvider.Instance();
            return dp.GetReferrals(r,pageSize,pageIndex);
        }

        #endregion

        #region Tests

        /// <summary>
        /// Returns the current referral. Will return null if no referral is available or if it is invalid.
        /// </summary>
        public static string GetReferralUrl(Uri referralUri, Uri currentUri, string agent, string filter)
        {

            //If no referral, return null
            if(referralUri == null)
                return null;

            //Nothing to validate against
            if( currentUri == null)
                return GetReferral(referralUri);
            
            //if we have a referral and a valid user agent
            if(FilerUserAgent(agent))
            {
                //referral host
                string rhost = Globals.HostPath(referralUri);

                //currnet host
                string chost = Globals.HostPath(currentUri);

                //is the referral @ the same host?
                if(string.Compare(rhost,chost,true) == 0)
                {
                    if(filter != null)
                    {
                        string path = referralUri.ToString().Remove(0,rhost.Length).ToLower();
                        if(!path.StartsWith(filter.ToLower()))
                        {
                            return GetReferral(referralUri);
                        }
                    }
                    else
                    {
                        return GetReferral(referralUri);
                    }
                    
                }
                else
                {
                   return GetReferral(referralUri);
                }
            }
            
            return null;
        }

        private static string GetReferral(Uri referralUri)
        {
            if(referralUri != null)
            {
                return referralUri.ToString().ToLower().Replace("www.",string.Empty);
            }
            return null;
        }

        public static string GetUriReferrerSafe(HttpRequest request)
        {
            string retVal = null;
    
            try
            {
                retVal = request.UrlReferrer.ToString();
            }
            catch{}
    
            return retVal;
        }

        private static bool FilerUserAgent(string agent)
        {
            // Most common browsers (except Opera & Lynx) contain "Mozilla" in useragent string
            // Some common bots do as well, so filter those out
            return (agent != null && agent.Length > 0 && Regex.IsMatch(agent,"msie|mozilla|opera|lynx",RegexOptions.IgnoreCase) && !Regex.IsMatch(agent, "slurp|jeeves|wisenutbot", RegexOptions.IgnoreCase));
        }

        #endregion
      
	}
}
