﻿using System;
using System.Text;

namespace Hedy.Sys
{
    public static class TokenHelper
    {
        private const char Base64PadCharacter = '=';
        private const char Base64Character62 = '+';
        private const char Base64Character63 = '/';
        private const char Base64UrlCharacter62 = '-';
        private const char Base64UrlCharacter63 = '_';
        private static Encoding textEncoding = Encoding.UTF8;

        public static string ReturnPayLoadJson(string accessToken)
        {
            var tokenParts = accessToken.Split('.');

            if (tokenParts.Length != 3)
                throw new ApplicationException("JWT Token must have three parts separated by '.' characters.");

            return Base64Decode(tokenParts[1]);
        }

        private static void ValidateLifetime(int nbf, int exp)
        {
            DateTime unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

            TimeSpan padding = new TimeSpan(0, 5, 0);

            DateTime validFrom = unixEpoch.AddSeconds(nbf); // a partir de
            DateTime validTo = unixEpoch.AddSeconds(exp); // até

            DateTime now = DateTime.UtcNow;

            if (now < (validFrom - padding))
                throw new ApplicationException(string.Format("The token is not valid until {0}.", validFrom));

            if (now > (validTo + padding))
                throw new ApplicationException(string.Format("The token is not valid after {0}.", validFrom));
        }

        private static byte[] DecodeBytes(string arg)
        {
            if (string.IsNullOrEmpty(arg))
                throw new ApplicationException("String to decode cannot be null or empty.");

            StringBuilder sb = new StringBuilder(arg);
            sb.Replace(Base64UrlCharacter62, Base64Character62);
            sb.Replace(Base64UrlCharacter63, Base64Character63);

            int pad = sb.Length % 4;
            sb.Append(Base64PadCharacter, (pad == 0) ? 0 : 4 - pad);

            return Convert.FromBase64String(sb.ToString());
        }

        private static string Base64Decode(string arg)
        {
            return textEncoding.GetString(DecodeBytes(arg));
        }
    }
}
