using System;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using System.Collections.Generic;
using System.Threading;
using System.Text;

namespace Tesses.Http
{
    public static class Extensions
    {
        private static Lazy<Dictionary<int, string>> _statusCodeMap = new Lazy<Dictionary<int, string>>(() => new Dictionary<int, string>()
        {
            [202] = "Accepted",
            [502] = "Bad Gateway",
            [400] = "Bad Request",
            [409] = "Conflict",
            [100] = "Continue",
            [201] = "Created",
            [417] = "Expectation Failed",
            [403] = "Forbidden",
            [302] = "Found",
            [504] = "Gateway Timeout",
            [410] = "Gone",
            [505] = "HTTP Version Not Supported",
            [500] = "Internal Server Error",
            [411] = "Length Required",
            [405] = "Method Not Allowed",
            [301] = "Moved Permanently",
            [300] = "Multiple Choices",
            [204] = "No Content",
            [203] = "Non Authoritative Information",
            [406] = "Not Acceptable",
            [404] = "Not Found",
            [501] = "Not Implemented",
            [304] = "Not Modified",
            [200] = "OK",
            [206] = "Partial Content",
            [402] = "Payment Required",
            [412] = "Precondition Failed",
            [407] = "Proxy Authentication Required",
            [302] = "Redirect",
            [307] = "Redirect Keep Verb",
            [303] = "Redirect Method",
            [416] = "Requested Range Not Satisfiable",
            [413] = "Request Entry Too Large",
            [408] = "Request Timeout",
            [414] = "Request Uri Too Long",
            [205] = "Reset Content",
            [503] = "Service Unavailable",
            [101] = "Switching Protocols",
            [307] = "Temporary Redirect",
            [401] = "Unauthorized",
            [415] = "Unsupported Media Type",
            [306] = "Unused",
            [426] = "Upgrade Required",
            [305] = "Use Proxy",
            [429] = "Too Many Requests"

        });
        public static byte[] AsArray(this Stream strm,bool begin=true)
        {
            if(strm.Position != 0 && begin)
                strm.Position=0;
            
            byte[] data=new byte[strm.Length-strm.Position];
            strm.Read(data,0,data.Length);
            return data;
        }
        public static string AsString(this byte[] data)
        {
            return Encoding.UTF8.GetString(data);
        }
        public static string GetReasonPhrase(this StatusLine line)
        {
        string res;
            if(_statusCodeMap.Value.TryGetValue(line.StatusCode,out res))
            {
                return res;
            }
            return "";
        }   
           /// <summary>
        /// StringBuilder ends with
        /// </summary>
        /// <param name="sb">string builder</param>
        /// <param name="test">text to check</param>
        /// <param name="comparison">comparison type</param>
        /// <returns>true if sb ends with test, false if it does not</returns>
        internal static bool EndsWith(this StringBuilder sb, string test,
    StringComparison comparison)
        {
            if (sb.Length < test.Length)
                return false;

            string end = sb.ToString(sb.Length - test.Length, test.Length);
            return end.Equals(test, comparison);
        }
        internal static string ReadHttpHeaders(this Stream strm)
        {
            StringBuilder s = new StringBuilder();

            var decoder = Encoding.UTF8.GetDecoder();
            var nextChar = new char[1];
            while (!s.EndsWith("\r\n\r\n",StringComparison.Ordinal))
            {

                int data = strm.ReadByte();
                if(data == -1)
                {
                    break;
                }
                int charCount=decoder.GetChars(new byte[] { (byte)data }, 0, 1, nextChar, 0);
                if (charCount == 0) continue;
                s.Append(nextChar);
             
            }
            
            
            return s.ToString();
        }
        

        public static void Add<T1,T2>(this Dictionary<T1,List<T2>> headers,T1 key,T2 value)
        {
            if(!headers.ContainsKey(key))
            {
                headers.Add(key,new List<T2>());
            }
            headers[key].Add(value);
        }
        public static bool TryGetFirst<T1,T2>(this Dictionary<T1,List<T2>> headers,T1 key,out T2 value)
        {
            value=default(T2);
            if(headers ==null) return false;
            if(headers.ContainsKey(key) && headers[key] !=null && headers[key].Count > 0)
            {
                value=headers[key][0];
                return true;
            }
            return false;
        }
        public static bool TryGetFirst<T>(this Dictionary<T,List<string>> headers,T key,out long value)
        {
            value=0;
            string v;
            
            return (headers.TryGetFirst(key,out v) && long.TryParse(v,out value));
        }
    }
}