using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
namespace InABox.Core
{
public static class LicenseUtils
{
#region License Generation
///
/// Generate a new, out-of-the-box license.
///
/// The new license, valid for 1 month.
public static LicenseData GenerateNewLicense()
{
return new LicenseData
{
LastRenewal = DateTime.Now,
Expiry = DateTime.Now.AddMonths(1),
CustomerID = Guid.Empty,
RenewalAvailable = DateTime.Now.AddMonths(1).AddDays(-7)
};
}
public static LicenseData RenewLicense(LicenseData oldLicense, DateTime renewed, DateTime newExpiry, DateTime renewAvailable)
{
return new LicenseData
{
LastRenewal = renewed,
Expiry = newExpiry,
CustomerID = oldLicense.CustomerID,
RenewalAvailable = renewAvailable
};
}
private static readonly byte[] LicenseKey = Convert.FromBase64String("dCyTyQkj1o1rqJJQlT+Jcnkxr+OQnO4KCoF/b+6cx54=");
///
/// Encrypts the license data.
///
/// The license to encrypt.
///
/// The encrypted data.
///
public static string? EncryptLicense(LicenseData license)
{
return Encryption.EncryptV2(Serialization.Serialize(license), LicenseKey);
}
public static bool TryEncryptLicense(LicenseData license, [NotNullWhen(true)] out string? result, [NotNullWhen(false)] out string? error)
{
return Encryption.TryEncryptV2(Serialization.Serialize(license), LicenseKey, out result, out error);
}
///
/// Decrypts .
///
/// The license to decrypt.
///
/// The new license data, or if errors occurred.
///
public static bool TryDecryptLicense(string data, [NotNullWhen(true)] out LicenseData? result, [NotNullWhen(false)] out string? error)
{
if (!Encryption.TryDecryptV2(data, LicenseKey, out var decrypted, out error))
{
result = null;
return false;
}
result = Serialization.Deserialize(decrypted);
if(result == null)
{
error = "License deserialization failed";
return false;
}
return true;
}
///
/// Decrypts , throwing an on fail.
///
/// The license to decrypt.
///
/// The new license data.
///
public static LicenseData DecryptLicense(string data)
{
if (!TryDecryptLicense(data, out var result, out var error))
throw new Exception(error);
return result;
}
#endregion
#region Fees & Discounts
private static readonly Dictionary _licensefees = new Dictionary();
private static readonly Dictionary _periods = new Dictionary();
private static readonly Dictionary _userDiscounts = new Dictionary();
public static double GetLicenseFee(Type type)
{
return _licensefees.GetValueOrDefault(type, 0);
}
public static double GetLicenseFee() where T : LicenseToken
{
return GetLicenseFee(typeof(T));
}
public static IEnumerable LicenseTypes()
{
return _licensefees.Keys;
}
public static double GetUserDiscount(int users)
{
var key = _userDiscounts.Keys
.Where(x => x <= users)
.DefaultIfEmpty(-1)
.Max();
if (key == -1)
return 0;
return _userDiscounts[key];
}
public static double GetTimeDiscount(int months)
{
var period = _periods.Keys
.Where(x => x <= months)
.DefaultIfEmpty(-1)
.Max();
if (period == -1)
return 0;
return _periods[period];
}
public static IEnumerable TimeDiscountLevels()
{
return _periods.Keys;
}
public static double CalculateLicenseFee(Dictionary licenses, int time)
{
double licensefee = 0.00F;
foreach (var license in licenses.Keys)
if (_licensefees.ContainsKey(license))
licensefee += _licensefees[license] * licenses[license];
var users = licenses.Values.OrderBy(x => x).LastOrDefault();
var userdiscount = GetUserDiscount(users);
var timediscount = GetTimeDiscount(time);
var result = licensefee * ((100.0F - userdiscount) / 100.0F) * ((100.0F - timediscount) / 100.0F);
return result;
}
public static void LoadSummary(LicenseSummary summary)
{
_licensefees.Clear();
_periods.Clear();
_userDiscounts.Clear();
foreach (var license in summary.LicenseFees)
_licensefees[CoreUtils.GetEntity(license.Key)] = license.Value;
foreach (var (months, period) in summary.TimeDiscounts)
_periods[months] = period;
foreach (var (users, discount) in summary.UserDiscounts)
_userDiscounts[users] = discount;
}
///
/// Gets a map from entities to their associated licenses.
///
/// A map of entity types to license types.
public static Dictionary LicenseMap()
{
var result = new Dictionary();
var licenses = CoreUtils.TypeList(
AppDomain.CurrentDomain.GetAssemblies(),
myType =>
myType.IsClass
&& !myType.IsAbstract
&& !myType.IsGenericType
&& myType.IsSubclassOf(typeof(LicenseToken))
).ToArray();
var entities = CoreUtils.TypeList(
AppDomain.CurrentDomain.GetAssemblies(),
myType =>
myType.IsClass
&& !myType.IsAbstract
&& !myType.IsGenericType
&& myType.IsSubclassOf(typeof(Entity))
).ToArray();
foreach (var entity in entities)
{
var lic = entity.GetInterfaces()
.FirstOrDefault(x => x.IsConstructedGenericType && x.GetGenericTypeDefinition() == typeof(ILicense<>));
result[entity] = lic?.GenericTypeArguments.FirstOrDefault();
}
return result;
}
public static void SaveLicenseSummary(string filename)
{
var entitymap = LicenseMap();
var summary = new List { "\"License Token\",\"Class Name\"" };
foreach (var mapentry in entitymap.OrderBy(x => x.Value))
summary.Add(string.Format("\"{0}\",\"{1}\"", mapentry.Value?.GetCaption(), mapentry.Value.EntityName()));
File.WriteAllLines(filename, summary.ToArray());
}
public static void Reset()
{
_licensefees.Clear();
_periods.Clear();
_userDiscounts.Clear();
}
#endregion
}
public class LicenseSummary
{
public LicenseSummary()
{
LicenseFees = new Dictionary();
TimeDiscounts = new Dictionary();
UserDiscounts = new Dictionary();
}
public Dictionary LicenseFees { get; set; }
public Dictionary TimeDiscounts { get; set; }
public Dictionary UserDiscounts { get; set; }
}
}