using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;

using System.Security.Cryptography;
using EQNetwork.Utility;

namespace EQNetwork.Utility
{
    public class AuthUtil
    {
        public static Dictionary<string, string> QueryStringToDictionary(string queryString) 
        {
            Dictionary<string, string> parms = new Dictionary<string,string>();

            var arr0 = queryString.Split('?'); // in case it gets an actual url
            string str = arr0[arr0.Length - 1];
            var arr1 = str.Split('&');
            foreach (var parm in arr1)
            {
                var arr2 = parm.Split('=');
                parms.Add(arr2[0], HttpUtility.UrlDecode(arr2[1]));
            }
            return parms;
        }

        const int kDefaultExpiresDurationInSeconds = 3600; // TODO: should be 300... but server clock problem
        public static string AuthenticateRequest(string httpVerb, string resourceUrl, string accessKey, string secret, string queryString)
        {
            var parms = QueryStringToDictionary(queryString);

            parms.Add("access_key", accessKey);
            if (!parms.ContainsKey("expires"))
                parms.Add("expires", (((long)(DateTime.Now - new DateTime(1970, 1, 1, 0, 0, 0, 0).ToLocalTime()).TotalSeconds) + kDefaultExpiresDurationInSeconds).ToString());

            Uri uri = new Uri(resourceUrl);

            StringBuilder strToSignBuilder = new StringBuilder(httpVerb.ToLower());
            strToSignBuilder.Append("|");
            strToSignBuilder.Append(uri.Host.ToLower());
            strToSignBuilder.Append("|");
            strToSignBuilder.Append(uri.AbsolutePath.ToLower());
            strToSignBuilder.Append("|");


            StringBuilder signedQueryString = new StringBuilder();            
            foreach (var pair in parms.OrderBy(i => i.Key))
            {
                if (signedQueryString.Length > 0)
                {
                    signedQueryString.Append("&");
                    strToSignBuilder.Append("&");
                }
                     
                signedQueryString.Append(HttpUtility.UrlEncode(pair.Key) + "=" + HttpUtility.UrlEncode(pair.Value));
                strToSignBuilder.Append(pair.Key + "=" + pair.Value);
            }

            System.Text.ASCIIEncoding asciiEncoding = new System.Text.ASCIIEncoding();
            byte[] hashValue = new HMACSHA256(asciiEncoding.GetBytes(secret)).ComputeHash(asciiEncoding.GetBytes(strToSignBuilder.ToString()));

            signedQueryString.Append("&signature=");
            signedQueryString.Append(HttpUtility.UrlEncode(System.Convert.ToBase64String(hashValue)));

            return signedQueryString.ToString();
        }

    }
}
