using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using Microsoft.AspNetCore.Cryptography.KeyDerivation;
namespace Sockeye.Util
{


    public static class Hasher
    {


        public static string hash(string Salt, string Password)
        {

            //adapted from here:
            //https://docs.microsoft.com/en-us/aspnet/core/security/data-protection/consumer-apis/password-hashing
            string hashed = Convert.ToBase64String(KeyDerivation.Pbkdf2(
                       password: Password,
                       salt: Convert.FromBase64String(Salt),
                       prf: KeyDerivationPrf.HMACSHA512,
                       iterationCount: 10000,
                       numBytesRequested: 512 / 8));
            return hashed;
        }

        //Generate salt
        /*
        Used for many things:
        DBID, JWT secret key when none provided, User Salt for login / password, 
        temporary 2fa codes, download tokens, 
        temporary user pw / login when newly created and haven't been set yet 
         */
        public static string GenerateSalt()
        { 
            var salt = new byte[32];
            var random = RandomNumberGenerator.Create();
            random.GetNonZeroBytes(salt);
            return Convert.ToBase64String(salt);
        }



        public static string GetRandomAlphanumericString(int length)
        {
            const string alphanumericCharacters = "0123456789abcdefghijkmnopqrstuvwxyz";
            return GetRandomString(length, alphanumericCharacters);
        }

        public static string GetRandomString(int length, IEnumerable<char> characterSet)
        {
            if (length < 0)
                throw new ArgumentException("length must not be negative", "length");
            if (length > int.MaxValue / 8) 
                throw new ArgumentException("length is too big", "length");
            if (characterSet == null)
                throw new ArgumentNullException("characterSet");
            var characterArray = characterSet.Distinct().ToArray();
            if (characterArray.Length == 0)
                throw new ArgumentException("characterSet must not be empty", "characterSet");
            var bytes = new byte[length * 8];
            RandomNumberGenerator.Create().GetBytes(bytes);
            var result = new char[length];
            for (int i = 0; i < length; i++)
            {
                ulong value = BitConverter.ToUInt64(bytes, i * 8);
                result[i] = characterArray[value % (uint)characterArray.Length];
            }
            return new string(result);
        }



    }//eoc

}//eons