/** Execute Head Request **************************************************/

        private async Task <MacroscopeRedirectChainDocStruct> _ExecuteHeadCheck(string Url)
        {
            MacroscopeHttpTwoClientResponse ClientResponse = null;
            Uri DocUri = null;
            MacroscopeRedirectChainDocStruct RedirectChainDocStruct = new MacroscopeRedirectChainDocStruct();

            try
            {
                DocUri = new Uri(Url);

                ClientResponse = await this.HttpClient.Head(
                    DocUri,
                    this.ConfigureHeadRequestHeadersCallback,
                    this.PostProcessRequestHttpHeadersCallback
                    );
            }
            catch (Exception ex)
            {
                this.DebugMsg(string.Format("_ExecuteHeadCheck :: Exception: {0}", ex.Message));
            }

            if (ClientResponse != null)
            {
                RedirectChainDocStruct = this.ProcessResponseHttpHeaders(Url: Url, Response: ClientResponse);
            }

            return(RedirectChainDocStruct);
        }
        /** Perform Probe *********************************************************/

        private async Task <MacroscopeRedirectChainDocStruct> Probe(string Url)
        {
            MacroscopeRedirectChainDocStruct RedirectChainDocStruct;

            try
            {
                if (this.RedirectChainDocCache.ContainsKey(Url))
                {
                    lock (this.RedirectChainDocCache)
                    {
                        RedirectChainDocStruct = this.RedirectChainDocCache[Url];
                    }
                }
                else
                {
                    RedirectChainDocStruct = new MacroscopeRedirectChainDocStruct();
                    try
                    {
                        RedirectChainDocStruct = await this._ExecuteHeadCheck(Url : Url);

                        lock (this.RedirectChainDocCache)
                        {
                            if (this.RedirectChainDocCache.ContainsKey(Url))
                            {
                                this.RedirectChainDocCache.Remove(Url);
                            }
                            this.RedirectChainDocCache.Add(Url, RedirectChainDocStruct);
                        }
                    }
                    catch (Exception ex)
                    {
                        this.DebugMsg(string.Format("_Probe :: Exception: {0}", ex.Message));
                    }
                }
            }
            catch (Exception ex)
            {
                RedirectChainDocStruct = new MacroscopeRedirectChainDocStruct();



                this.DebugMsg(ex.Message);
            }

            return(RedirectChainDocStruct);
        }
        /**************************************************************************/

        private MacroscopeRedirectChainDocStruct ProcessResponseHttpHeaders(string Url, MacroscopeHttpTwoClientResponse Response)
        {
            HttpResponseMessage ResponseMessage = Response.GetResponse();
            HttpResponseHeaders ResponseHeaders = ResponseMessage.Headers;
            HttpContentHeaders  ContentHeaders  = ResponseMessage.Content.Headers;
            MacroscopeRedirectChainDocStruct RedirectChainDocStruct = new MacroscopeRedirectChainDocStruct();

            /** HTTP Status Code ------------------------------------------------- **/

            RedirectChainDocStruct.StatusCode = Response.GetResponse().StatusCode;

            /** URL ------------------------------------------------- **/

            RedirectChainDocStruct.Url = Url;

            /** Location HTTP Header --------------------------------------------- **/

            try
            {
                Uri HeaderValue = ResponseHeaders.Location;
                if (HeaderValue != null)
                {
                    RedirectChainDocStruct.RedirectUrl = HeaderValue.ToString();
                }
            }
            catch (Exception ex)
            {
                this.DebugMsg(ex.Message);
                FindHttpResponseHeaderCallback Callback = delegate(IEnumerable <string> HeaderValues)
                {
                    RedirectChainDocStruct.RedirectUrl = HeaderValues.First().ToString();
                    return(true);
                };
                if (!this.FindHttpResponseHeader(ResponseHeaders: ResponseHeaders, HeaderName: "location", Callback: Callback))
                {
                    this.FindHttpContentHeader(ContentHeaders: ContentHeaders, HeaderName: "location", Callback: Callback);
                }
            }

            /** ------------------------------------------------------------------ **/

            return(RedirectChainDocStruct);
        }
        /**************************************************************************/

        public async Task <List <MacroscopeRedirectChainDocStruct> > AnalyzeRedirectChains(
            HttpStatusCode StatusCode,
            string StartUrl,
            string RedirectUrl
            )
        {
            List <MacroscopeRedirectChainDocStruct> RedirectChain = new List <MacroscopeRedirectChainDocStruct>();
            int MaxHops = MacroscopePreferencesManager.GetRedirectChainsMaxHops();
            MacroscopeRedirectChainDocStruct StructStart;
            int    IHOP    = 0;
            string PrevUrl = null;
            string NextUrl = null;

            try
            {
                try
                {
                    StructStart = new MacroscopeRedirectChainDocStruct(
                        NewStatusCode: StatusCode,
                        NewUrl: StartUrl,
                        NewRedirectUrl: RedirectUrl
                        );

                    RedirectChain.Add(StructStart);

                    PrevUrl = StructStart.Url;
                    NextUrl = StructStart.RedirectUrl;
                }
                catch (Exception ex)
                {
                    this.DebugMsg(ex.Message);
                }

                do
                {
                    MacroscopeRedirectChainDocStruct StructNext;

                    try
                    {
                        if (!string.IsNullOrEmpty(PrevUrl))
                        {
                            NextUrl = MacroscopeHttpUrlUtils.MakeUrlAbsolute(PrevUrl, NextUrl);
                        }

                        StructNext = await this.Probe(Url : NextUrl);

                        RedirectChain.Add(StructNext);

                        PrevUrl = StructNext.Url;
                        NextUrl = StructNext.RedirectUrl;


                        switch (StructNext.StatusCode)
                        {
                        case HttpStatusCode.Found:
                            break;

                        case HttpStatusCode.Moved:
                            break;

                        case HttpStatusCode.SeeOther:
                            break;

                        case HttpStatusCode.TemporaryRedirect:
                            break;

                        default:
                            IHOP = MaxHops;
                            break;
                        }
                    }
                    catch (Exception ex)
                    {
                        this.DebugMsg(ex.Message);
                    }

                    IHOP++;
                }while(IHOP < MaxHops);
            }
            catch (Exception ex)
            {
                this.DebugMsg(ex.Message);
            }

            return(RedirectChain);
        }