using System;
using System.Collections.Generic;
using System.Text;
using System.Web;
using B4Restore.Common.Web;
using System.Text.RegularExpressions;

namespace DebriefingSoftware.Common.Web.Navigation
{
    public static class UriEscaper
    {
        public static string EscapeUriString(this string sourceUrl)
        {
            return sourceUrl.EscapeUriStringOnce().EscapeUriStringOnce();
        }

        public static string EscapeUriStringOnce(this string sourceUrl)
        {
            if (sourceUrl == null)
            {
                throw new ArgumentNullException("sourceUrl");
            }

            return Uri.EscapeUriString(sourceUrl).Replace(":", "%3A").Replace("javascript%3A", "javascript:");
        }

        public static string RemoveSessionIdentifier(this string sourceUrl)
        {
            if (sourceUrl == null)
                throw new ArgumentNullException("sourceUrl");

            return Regex.Replace(sourceUrl, @"\/\(S\([A-z0-9]+\)\)", "");
        }

        public static string UnEscapeUriStringOnce(this string sourceUrl)
        {
            if (sourceUrl == null)
            {
                throw new ArgumentNullException("sourceUrl");
            }
            return Uri.UnescapeDataString(sourceUrl).Replace("+", " ");
        }

        public static string ApplyAppPathModifier(this string sourceUrl)
        {
            if (sourceUrl == null)
                throw new ArgumentNullException("sourceUrl");
            if (HttpContext.Current == null)
                throw new InvalidOperationException("Code is running under not a web application.");

            return HttpContext.Current.Response.ApplyAppPathModifier(sourceUrl);
        }

        public static string ApplyQueryParams(this string sourceUrl, IDictionary<string, object> parameters)
        {
            if (sourceUrl == null)
                throw new ArgumentNullException("sourceUrl");

            var dic = new Dictionary<string, string>();
            if (parameters != null)
                foreach (var keyValue in parameters)
                    dic.Add(keyValue.Key, keyValue.Value == null ? null : keyValue.Value.ToString());

            return sourceUrl.ApplyQueryParams(dic);
        }

        public static string ApplyQueryParams(this string sourceUrl, IDictionary<string, string> parameters)
        {
            if (sourceUrl == null)
                throw new ArgumentNullException("sourceUrl");

            var isSourceUrlContainOtherParametes = sourceUrl.IndexOf("?", StringComparison.OrdinalIgnoreCase) > -1;

            var queryParams = new StringBuilder();
            if (parameters != null)
                foreach (var dictionary in parameters)
                    queryParams.AppendFormat("{0}={1}&", dictionary.Key, dictionary.Value);

            return string.Format("{0}{1}{2}",
                                 sourceUrl,
                                 isSourceUrlContainOtherParametes ? "&" : "?",
                                 queryParams
                );
        }

        public static string ApplyQueryParams(this string sourceUrl, params string[] parameters)
        {
            if (sourceUrl == null)
                throw new ArgumentNullException("sourceUrl");

            var isSourceUrlContainOtherParametes = sourceUrl.IndexOf("?", StringComparison.OrdinalIgnoreCase) > -1;

            var queryParams = new StringBuilder();
            if (parameters != null)
            {
                if (parameters.Length % 2 != 0)  // the count should be even (the parameter name and value pairs)
                    throw new ArgumentException("parameters");

                for (int i = 0; i < parameters.Length; i += 2)
                {
                    queryParams.AppendFormat("{0}={1}&", parameters[i], parameters[i + 1]);
                }
            }
            string sResult = string.Format("{0}{1}{2}", sourceUrl, isSourceUrlContainOtherParametes ? "&" : "?", queryParams);
            return sResult;
        }

        /// <summary>
        /// One of key methods to use.
        /// Usage:
        /// "~/Pages/IOgrp.aspx".AQPEscapeOnceAbsolute(UrlConst.SVC__CLUSTER__ID, nodeList[i].Cluster_id,
        ///             UrlConst.SVC__IO_GRP__ID, nodeList[i].Io_group_id.ToString())
        /// </summary>
        //  Return example: "http://localhost/Client.TSM-SVC/(S(yp0upf45xwe3uv454rqxyhe2))/Pages/IOgrp.aspx?svc.cluster.id=0000020060A00832&svc.io_grp_state.id=0&"
        public static string AQPEscapeOnceAbsolute(this string sourceUrl, params string[] parameters)
        {
            return HttpContext.Current.GetAbsolutePath(sourceUrl.EscapeUriStringOnce().ApplyAppPathModifier().ApplyQueryParams(parameters));
        }
    }
}