/// <summary>
		/// Returns all available URIs (audio-only and video) for the given YouTube ID. 
		/// </summary>
		public static async Task<YouTubeUri[]> GetUrisAsync(string youTubeId, IResourceNetworkLayer networkLayer, IProgress<float> progress, CancellationToken token)
		{
			var urls = new List<YouTubeUri>();
			string javaScriptCode = null;

			var response = await HttpGet("https://www.youtube.com/watch?v=" + youTubeId + "&nomobile=1", networkLayer, progress, token);
			var match = Regex.Match(response, "url_encoded_fmt_stream_map\": ?\"(.*?)\"");
			var data = Uri.UnescapeDataString(match.Groups[1].Value);
			match = Regex.Match(response, "adaptive_fmts\": ?\"(.*?)\"");
			var data2 = Uri.UnescapeDataString(match.Groups[1].Value);

			var arr = Regex.Split(data + "," + data2, ",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)"); // split by comma but outside quotes
			foreach (var d in arr)
			{
				var url = "";
				//var connection = "";
				//var stream = "";
				var signature = "";
				var tuple = new YouTubeUri();
				foreach (var p in d.Replace("\\u0026", "\t").Split('\t'))
				{
					var index = p.IndexOf('=');
					if (index != -1 && index < p.Length)
					{
						try
						{
							var key = p.Substring(0, index);
							var value = Uri.UnescapeDataString(p.Substring(index + 1));
							if (key == "url")
								url = value;
							//else if (key == "conn")
							//    connection = value;
							//else if (key == "stream")
							//    stream = value;
							else if (key == "itag")
								tuple.Itag = int.Parse(value);
							else if (key == "type" && (value.Contains("video/mp4") || value.Contains("audio/mp4")))
								tuple.Type = value;
							else if (key == "sig")
								signature = value;
							else if (key == "s")
							{
								if (javaScriptCode == null)
								{
									var javaScriptUri = "http://s.ytimg.com/yts/jsbin/html5player-" +
														Regex.Match(response,
															"\"\\\\/\\\\/s.ytimg.com\\\\/yts\\\\/jsbin\\\\/html5player-(.+?)\\.js\"")
															.Groups[1] + ".js";
									javaScriptCode = await HttpGet(javaScriptUri, networkLayer, progress, token);
								}

								signature = GenerateSignature(value, javaScriptCode);
							}
						}
						catch (Exception exception)
						{
							Debug.WriteLine("YouTube parse exception: " + exception.Message);
						}
					}
				}

				//if (string.IsNullOrEmpty(url) && !string.IsNullOrEmpty(connection) && !string.IsNullOrEmpty(stream))
				//{
				//    url = connection + "?" + stream; 
				//}

				if (url.Contains("&signature=") || url.Contains("?signature="))
					tuple._url = url;
				else
					tuple._url = url + "&signature=" + signature;

				if (tuple.IsValid)
					urls.Add(tuple);
			}

			return urls.ToArray();
		}
        /// <summary>
        /// Returns all available URIs (audio-only and video) for the given YouTube ID.
        /// </summary>
        public static async Task <YouTubeUri[]> GetUrisAsync(string youTubeId, IResourceNetworkLayer networkLayer, IProgress <float> progress, CancellationToken token)
        {
            var    urls           = new List <YouTubeUri>();
            string javaScriptCode = null;

            var response = await HttpGet("https://www.youtube.com/watch?v=" + youTubeId + "&nomobile=1", networkLayer, progress, token);

            var match = Regex.Match(response, "url_encoded_fmt_stream_map\": ?\"(.*?)\"");
            var data  = Uri.UnescapeDataString(match.Groups[1].Value);

            match = Regex.Match(response, "adaptive_fmts\": ?\"(.*?)\"");
            var data2 = Uri.UnescapeDataString(match.Groups[1].Value);

            var arr = Regex.Split(data + "," + data2, ",(?=(?:[^\"]*\"[^\"]*\")*[^\"]*$)");             // split by comma but outside quotes

            foreach (var d in arr)
            {
                var url = "";
                //var connection = "";
                //var stream = "";
                var signature = "";
                var tuple     = new YouTubeUri();
                foreach (var p in d.Replace("\\u0026", "\t").Split('\t'))
                {
                    var index = p.IndexOf('=');
                    if (index != -1 && index < p.Length)
                    {
                        try
                        {
                            var key   = p.Substring(0, index);
                            var value = Uri.UnescapeDataString(p.Substring(index + 1));
                            if (key == "url")
                            {
                                url = value;
                            }
                            //else if (key == "conn")
                            //    connection = value;
                            //else if (key == "stream")
                            //    stream = value;
                            else if (key == "itag")
                            {
                                tuple.Itag = int.Parse(value);
                            }
                            else if (key == "type" && (value.Contains("video/mp4") || value.Contains("audio/mp4")))
                            {
                                tuple.Type = value;
                            }
                            else if (key == "sig")
                            {
                                signature = value;
                            }
                            else if (key == "s")
                            {
                                if (javaScriptCode == null)
                                {
                                    var javaScriptUri = "http://s.ytimg.com/yts/jsbin/html5player-" +
                                                        Regex.Match(response,
                                                                    "\"\\\\/\\\\/s.ytimg.com\\\\/yts\\\\/jsbin\\\\/html5player-(.+?)\\.js\"")
                                                        .Groups[1] + ".js";
                                    javaScriptCode = await HttpGet(javaScriptUri, networkLayer, progress, token);
                                }

                                signature = GenerateSignature(value, javaScriptCode);
                            }
                        }
                        catch (Exception exception)
                        {
                            Debug.WriteLine("YouTube parse exception: " + exception.Message);
                        }
                    }
                }

                //if (string.IsNullOrEmpty(url) && !string.IsNullOrEmpty(connection) && !string.IsNullOrEmpty(stream))
                //{
                //    url = connection + "?" + stream;
                //}

                if (url.Contains("&signature=") || url.Contains("?signature="))
                {
                    tuple._url = url;
                }
                else
                {
                    tuple._url = url + "&signature=" + signature;
                }

                if (tuple.IsValid)
                {
                    urls.Add(tuple);
                }
            }

            return(urls.ToArray());
        }