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

using System;
using System.Collections;
using System.Collections.Specialized;
using System.Configuration;
using System.Web;
using System.Globalization;
using System.Text.RegularExpressions;
using System.Text;

using CommunityServer.Configuration;


namespace CommunityServer.Components {

    public class Globals {

        // the HTML newline character
        public const String HtmlNewLine = "<br />";
        public const String _appSettingsPrefix = "AspNetForumsSettings.";
		public static Regex _pathComponentTextToEscape = new Regex(@"([^A-Za-z0-9\- ]+|\.| )", RegexOptions.Singleline | RegexOptions.Compiled);
		public static Regex _pathComponentTextToUnescape = new Regex(@"((?:_(?:[0-9a-f][0-9a-f][0-9a-f][0-9a-f])+_)|\+)", RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.Compiled);
		public static Regex _fileComponentTextToEscape = new Regex(@"([^A-Za-z0-9 ]+|\.| )", RegexOptions.Singleline | RegexOptions.Compiled);
		public static Regex _fileComponentTextToUnescape = new Regex(@"((?:_(?:[0-9a-f][0-9a-f][0-9a-f][0-9a-f])+_)|_|\-)", RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.Compiled);


		public static void ValidateSecureConnection(SSLSettings ssl, HttpContext context)
		{
			//Validate we have a secure connection as early as possible
			if(CSConfiguration.GetConfig().SSL == ssl)
			{
				RedirectToSSL(context);
			}
		}

        public static void RedirectToSSL(HttpContext context)
        {
            if(!context.Request.IsSecureConnection)
            {
                Uri url = context.Request.Url;
                context.Response.Redirect("https://" + url.ToString().Substring(7));
               // context.Response.End();
            }   
        }

		/// <summary>
		/// Will return false if no Url querystring value can be found
		/// </summary>
		/// <returns></returns>
		public static bool RedirectSiteUrl()
		{

			CSContext cntx = CSContext.Current;
			if(cntx.Url != null)
			{
				RedirectSiteUrl( cntx.Url, cntx.Args );
			}

			return false;
		}
		public static void RedirectSiteUrl(string path) { RedirectSiteUrl( path, null ); }

		public static void RedirectSiteUrl(string path, string args)
		{
			CSContext cntx = CSContext.Current;

			if(cntx.IsWebRequest)
			{
				try
				{
					if(args == null)
						cntx.Context.Response.Redirect(Globals.GetSiteUrls().RawPath(path));
					else
						cntx.Context.Response.Redirect(string.Format(Globals.GetSiteUrls().RawPath(path), args.Split(',')), true);
				}
				catch { }
			}
			throw new CSException(CSExceptionType.RedirectFailure);
		}

        #region FormatSignature
        public static string FormatSignature (string userSignature) 
        {
            if ( userSignature != null && userSignature.Length > 0 )
                return "<hr size=\"1\" align=\"left\" width=\"25%\">" + userSignature.Replace("\r\n", "<br>");
			else
				return String.Empty;
        }
        #endregion

        #region Trace
        public static void Trace(string category, string message) 
        {

            if (!CSContext.Current.SiteSettings.EnableDebugMode)
                return;

            HttpContext context = HttpContext.Current;
            Stack debugStack;

            // Do we have the debug stack?
            //
            if (context.Items["DebugTrace"] == null)
                debugStack = new Stack();
            else
                debugStack = (Stack) context.Items["DebugTrace"];

            // Add a new item
            //
            debugStack.Push(new DebugTrace(category, message));

            // Add item to general ASP.NET trace
            //
            context.Trace.Write(category, message);

        }

        public class DebugTrace {
            DateTime time;
            string category;
            string message;

            public DebugTrace(string category, string message) {
                this.category = category;
                this.message = message;
                time = DateTime.Now;
            }

            public DateTime Time { get { return time; } }
            public string Category { get { return category; } }
            public string Message { get { return message; } }

        }

        #endregion

        #region Encode/Decode
        /// <summary>
        /// Converts a prepared subject line back into a raw text subject line.
        /// </summary>
        /// <param name="textToFormat">The prepared subject line.</param>
        /// <returns>A raw text subject line.</returns>
        /// <remarks>This function is only needed when editing an existing message or when replying to
        /// a message - it turns the HTML escaped characters back into their pre-escaped status.</remarks>
        public static string HtmlDecode(String textToFormat) 
        {   
            if(IsNullorEmpty(textToFormat))
                return textToFormat;
            
            //ScottW: Removed Context dependency
            return System.Web.HttpUtility.HtmlDecode(textToFormat);
            // strip the HTML - i.e., turn < into &lt;, > into &gt;
            //return HttpContext.Current.Server.HtmlDecode(FormattedMessageSubject);
        } 

        /// <summary>
        /// Converts a prepared subject line back into a raw text subject line.
        /// </summary>
        /// <param name="textToFormat">The prepared subject line.</param>
        /// <returns>A raw text subject line.</returns>
        /// <remarks>This function is only needed when editing an existing message or when replying to
        /// a message - it turns the HTML escaped characters back into their pre-escaped status.</remarks>
        public static string HtmlEncode(String textToFormat) {       
            // strip the HTML - i.e., turn < into &lt;, > into &gt;

            if(IsNullorEmpty(textToFormat))
                return textToFormat;

            //ScottW: Removed Context dependency
            return System.Web.HttpUtility.HtmlEncode(textToFormat);
            //return HttpContext.Current.Server.HtmlEncode(FormattedMessageSubject);
        } 
        
        public static string UrlEncode(string urlToEncode)
        {
            if(IsNullorEmpty(urlToEncode))
                return urlToEncode;

            return System.Web.HttpUtility.UrlEncode(urlToEncode).Replace("'","%27");
;
        }

		public static string UrlDecode(string urlToDecode)
		{
			if(IsNullorEmpty(urlToDecode))
				return urlToDecode;

			return System.Web.HttpUtility.UrlDecode(urlToDecode);
		}

		public static string UrlEncodePathComponent(string text)
		{
			return UrlEncode(text, _pathComponentTextToEscape, '+', '_');
		}

		public static string UrlDecodePathComponent(string text)
		{
			return UrlDecode(text, _pathComponentTextToUnescape);
		}

		public static string UrlEncodeFileComponent(string text)
		{
			return UrlEncode(text, _fileComponentTextToEscape, '-', '_');
		}

		public static string UrlDecodeFileComponent(string text)
		{
			return UrlDecode(text, _fileComponentTextToUnescape);
		}

		private static string UrlEncode(string text, Regex pattern, char spaceReplacement, char escapePrefix)
		{
			if (IsNullorEmpty(text))
				return text;

			Match match = pattern.Match(text);
			StringBuilder encText = new StringBuilder();
			int lastEndIndex = 0;
			while (match.Value != string.Empty)
			{
				if (lastEndIndex != match.Index)
					encText.Append(text.Substring(lastEndIndex, match.Index - lastEndIndex));

				if (match.Value == " ")
					encText.Append(spaceReplacement);
				else if (match.Value == "." && match.Index != text.Length - 1)
					encText.Append("."); // . at the end of text causes a 404... only encode . at the end of text
				else
				{
					encText.Append(escapePrefix);
					byte[] bytes = Encoding.Unicode.GetBytes(match.Value);
					if (bytes != null)
					{
						foreach (byte b in bytes)
						{
							string hexByte = b.ToString("X");

							if (hexByte.Length == 1)
								encText.Append("0");

							encText.Append(hexByte);
						}
					}
					encText.Append(escapePrefix);
				}

				lastEndIndex = match.Index + match.Length;
				match = pattern.Match(text, lastEndIndex);
			}

			if (lastEndIndex < text.Length)
				encText.Append(text.Substring(lastEndIndex));

			return encText.ToString();
		}

		private static string UrlDecode(string text, Regex pattern)
		{
			if (IsNullorEmpty(text))
				return text;

			Match match = pattern.Match(text);
			StringBuilder decText = new StringBuilder();
			int lastEndIndex = 0;
			while (match.Value != string.Empty)
			{
				if (lastEndIndex != match.Index)
					decText.Append(text.Substring(lastEndIndex, match.Index - lastEndIndex));

				if (match.Value.Length == 1)
					decText.Append(" ");
				else
				{
					byte[] bytes = new byte[(match.Value.Length - 2) / 2];

					for (int i = 1; i < match.Value.Length - 1; i+=2)
						bytes[(i - 1) / 2] = byte.Parse(match.Value.Substring(i, 2), NumberStyles.AllowHexSpecifier);

					decText.Append(Encoding.Unicode.GetString(bytes));
				}

				lastEndIndex = match.Index + match.Length;
				match = pattern.Match(text, lastEndIndex);
			}

			if (lastEndIndex < text.Length)
				decText.Append(text.Substring(lastEndIndex));

			return decText.ToString();
		}

        #endregion

        #region DefaultForumView
        /************ PROPERTY SET/GET STATEMENTS **************/
        /// <summary>
        /// Returns the default view to use for viewing the forum posts, as specified in the AspNetForumsSettings
        /// section of Web.config.
        /// </summary>
        static public int DefaultForumView 
        {
            get {
                const int _defaultForumView = 2;
                const String _settingName = "defaultForumView";

                String _str = CSCache.Get("webForums." + _settingName) as String;
                int iValue = _defaultForumView;
                if (_str == null) {
                    // we need to get the string and place it in the cache
                    String prefix = "";
                    NameValueCollection context = (NameValueCollection)ConfigurationSettings.GetConfig("AspNetForumsSettings");
                    if (context == null) {
                        // get the appSettings context
                        prefix = Globals._appSettingsPrefix;;
                        context = (NameValueCollection)ConfigurationSettings.GetConfig("appSettings");
                    }

                    _str = context[prefix + _settingName];

                    // determine what forum view to show
                    if (_str == null)
                        // choose the default
                        iValue = _defaultForumView;
                    else
                        switch(_str.ToUpper()) {
                            case "THREADED":
                                iValue = 2;
                                break;

                            case "MIXED":
                                iValue = 1;
                                break;

                            case "FLAT":
                                iValue = 0;
                                break;

                            default:
                                iValue = _defaultForumView;
                                break;
                        }
                    
                    _str = iValue.ToString();
                    
                    CSCache.Insert("webForums." + _settingName, _str);
                }

                return Convert.ToInt32(_str);
            }
        }
        #endregion

        #region Skin/App Paths
        static public String GetSkinPath() 
        {

            // TODO -- Need to get the full path if the application path is not available
            try {
                if (CSConfiguration.GetConfig().FilesPath == "/")
                    return ApplicationPath + "/Themes/" + CSContext.Current.User.Theme;
                else
                    return ApplicationPath + CSConfiguration.GetConfig().FilesPath + "/Themes/" + CSContext.Current.User.Theme;
            } catch {
                return "";
            }
        }

        static public string ApplicationPath {

            get {
                string applicationPath = "/";
				
				if(HttpContext.Current != null)
					applicationPath = HttpContext.Current.Request.ApplicationPath;

                // Are we in an application?
                //
                if (applicationPath == "/") {
                    return string.Empty;
                } else {
                    return applicationPath;
                }
            }

        }



        static public SiteUrls GetSiteUrls() 
        {
            return SiteUrls.Instance();
        }

        #endregion

        #region Language
        static public string Language 
        {
            get {
				return CSConfiguration.GetConfig().DefaultLanguage;
            }
        }
        #endregion

      

        #region CreateTemporaryPassword Replaced by WSHA
        /// <summary>
        /// Creates a temporary password of a specified length.
        /// </summary>
        /// <param name="length">The maximum length of the temporary password to create.</param>
        /// <returns>A temporary password less than or equal to the length specified.</returns>
//        public static String CreateTemporaryPassword(int length) 
//        {
//
//            string strTempPassword = Guid.NewGuid().ToString("N");
//
//            for(int i = 0; i < (length / 32); i++) {
//                strTempPassword += Guid.NewGuid().ToString("N");
//            }
//
//            return strTempPassword.Substring(0, length);
//        }
        #endregion

        public static int SafeInt(string text, int defaultValue)
        {
            if(!IsNullorEmpty(text))
            {
                try
                {
                    return Int32.Parse(text);
                }
                catch(Exception){}
                
            }

            return defaultValue;
        }

		public static bool SafeBool(string text, bool defaultValue)
		{
			if(!IsNullorEmpty(text))
			{
				try
				{
					return bool.Parse(text);
				}
				catch(Exception){}
                
			}

			return defaultValue;
		}

        public static bool IsNullorEmpty(string text)
        {
            return text == null || text.Trim() == string.Empty;
        }

		public static bool IsDate(string text)
		{
			if(IsNullorEmpty(text))
				return false;

            try
			{
				DateTime dt = DateTime.Parse(text);
				return true;
			}
			catch(Exception){}

			return false;
		}


        public static string HostPath(Uri uri)
        {
            string portInfo = uri.Port == 80 ? string.Empty : ":" + uri.Port.ToString();
            return string.Format("{0}://{1}{2}",uri.Scheme,uri.Host, portInfo);
        }

        public static string FullPath(string local)
        {
            if(IsNullorEmpty(local))
                return local;

			if (local.ToLower().StartsWith("http://") || local.ToLower().StartsWith("https://"))
                return local;

			if(HttpContext.Current == null)
				return local;

            return FullPath(HostPath(HttpContext.Current.Request.Url),local);
        }

        public static string FullPath(string hostPath, string local)
        {
            return hostPath + local;
        }

		/// <summary>
		/// Adds a string to the current url determining the correct seperator character
		/// </summary>
		/// <param name="url"></param>
		/// <param name="querystring"></param>
		/// <returns></returns>
		public static string AppendQuerystring(string url, string querystring)
		{
			return AppendQuerystring (url,querystring, false);
		}
		public static string AppendQuerystring(string url, string querystring, bool urlEncoded)
		{
			string seperator = "?";
			if(url.IndexOf('?') > -1)
			{
				if(!urlEncoded)
					seperator = "&";
				else
					seperator = "&amp;";
			}
			return string.Concat(url, seperator, querystring); 	
		}



		public static bool ValidateApplicationKey(string appKey, out string formattedKey)
		{
			formattedKey = appKey.Trim().Replace(" ", "_").ToLower();
			formattedKey = System.Text.RegularExpressions.Regex.Replace(formattedKey, "[^0-9a-zA-Z_\\-]", "");

			//Should we remove these items? Or just encode them. We can change this logic 
			//string[] parts = formattedKey.Split('!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '[', ']', '{', '}', '<', '>', ',', '?', '\\', '/', '\'','+','=','~','`','|');
			//formattedKey =  string.Join("", parts);

			formattedKey = Globals.UrlEncode(formattedKey);

            return formattedKey == appKey;
		}

        public static void Return404(HttpContext Context)
        {
            Context.Response.StatusCode = 404;    
            Context.Response.SuppressContent = true;    
            Context.Response.End();
        }

		public static string JoinIntArray(string separator, int[] intArray)
		{
			if (intArray != null && intArray.Length > 0)
			{
				StringBuilder sb = new StringBuilder();
				for (int i = 0; i <= intArray.GetUpperBound(0); i++)
				{
					if (i != 0)
						sb.Append(separator);
					sb.Append(intArray[i]);
				}
				return sb.ToString();
			}
			else
			{
				return string.Empty;
			}
		}

    }
}
