using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using InABox.Clients;
using InABox.Core;
using InABox.DynamicGrid;
using InABox.Wpf;
using InABox.WPF;
using System.Windows.Controls;
using System.Drawing;
using Image = System.Windows.Controls.Image;
using System.Diagnostics;
using InABox.Client.Remote.Json;
using InABox.Configuration;
using Microsoft.Win32;
using PRS.Shared;
using Stripe;
namespace PRSServer.Forms.DatabaseLicense;
///
/// Interaction logic for LicenseRenewal.xaml
///
public partial class LicenseRenewalForm : ThemableWindow, IDynamicEditorHost
{
public static HttpJsonClient LicenseClient = new("https", "remote.prsdigital.com.au", 5000);
//public static HttpJsonClient LicenseClient = new("http", "127.0.0.1", 8001);
private static readonly EncryptedLocalConfiguration _config = new("g6+BoQpyti5bHsTZOY5Nbqq3Q3c90n0m3qZaQ3eAwkk=");
private LicenseRegistrationDetails _licenseRegistrationDetails;
private LicenseData? _currentLicense;
public LicenseData? CurrentLicense
{
get => _currentLicense;
set
{
_currentLicense = value;
Modules.CurrentLicense = value;
}
}
public int RenewalPeriod
{
get
{
if (int.TryParse(RenewalPeriodEditor.Value?.ToString(), out var period))
{
return period;
}
return 0;
}
set
{
RenewalPeriodEditor.Value = value;
CalculateDiscounts();
}
}
public DateTime RenewalDate
{
get
{
if(CurrentLicense == null)
{
return DateTime.MinValue;
}
if (CurrentLicense.Expiry > DateTime.Now)
{
return CurrentLicense.Expiry.Date;
}
return DateTime.Today;
}
}
private DateTime _renewalAvailable;
public DateTime RenewalAvailableFrom
{
get => _renewalAvailable;
set
{
_renewalAvailable = value;
if (!CanRenew)
{
RenewalAvailableLabel.Content = $"Renewal available from {value:dd MMM yyyy}";
}
}
}
public bool CanRenew => RenewalAvailableFrom.Date <= DateTime.Today || (CurrentLicense != null && CurrentLicense.Expiry <= DateTime.Now);
public DateTime NewExpiration
{
get => RenewalDate.AddMonths(RenewalPeriod);
}
public List LicenseItems { get; private set; }
public int Licenses { get; private set; }
public double Gross { get; private set; }
public double Discount { get; private set; }
public double Net => Gross - Discount;
public LicenseRenewalForm()
{
InitializeComponent();
// This should get us the RegistrationID, which we need in order
// to get the License Pricing from the Server
_licenseRegistrationDetails = _config.Load(false);
LastRenewal.EditorDefinition = new DateEditor();
LastRenewal.Configure();
LastRenewal.IsEnabled = false;
CurrentExpiry.EditorDefinition = new DateEditor();
CurrentExpiry.Configure();
CurrentExpiry.IsEnabled = false;
RenewalPeriodEditor.EditorDefinition = new ComboLookupEditor(typeof(RenewalPeriodLookups));
RenewalPeriodEditor.Host = this;
RenewalPeriodEditor.Configure();
var lookups = new RenewalPeriodLookups(null).AsTable("RenewalPeriod");
RenewalPeriodEditor.LoadLookups(lookups);
NewExpiry.EditorDefinition = new DateEditor();
NewExpiry.Configure();
NewExpiry.IsEnabled = false;
GrossLicenseFee.EditorDefinition = new CurrencyEditor();
GrossLicenseFee.Configure();
GrossLicenseFee.IsEnabled = false;
DiscountEditor.EditorDefinition = new DoubleEditor();
DiscountEditor.Configure();
DiscountEditor.IsEnabled = false;
NettLicenseFee.EditorDefinition = new CurrencyEditor();
NettLicenseFee.Configure();
NettLicenseFee.IsEnabled = false;
Help.Content = new Image { Source = Properties.Resources.help.AsBitmapImage(Color.White) };
Help.Click += Help_Click;
}
private void Help_Click(object sender, RoutedEventArgs e)
{
Process.Start(new ProcessStartInfo("https://prsdigital.com.au/wiki/index.php/License_Renewal") { UseShellExecute = true });
}
private void LoadData()
{
var result = Progress.ShowModal("Getting License", progress =>
{
try
{
progress.Report("Loading License");
CurrentLicense = LoadCurrentLicense();
progress.Report("Checking Server");
if (!LicenseClient.Ping("ping"))
return Result.Error("Server Unavailable");
progress.Report("Retrieving Data");
RetrieveFees();
progress.Report("Scanning Data");
LoadUserTracking();
foreach (var item in LicenseItems)
item.Rate = LicenseUtils.GetLicenseFee(item.Type);
return Result.Ok(true);
}
catch (Exception e)
{
return Result.Error(e.Message);
}
});
if (result.Get(out var success, out var error) && success)
{
UpdateWindow();
}
else
{
MessageWindow.ShowMessage(error ?? "Error", "Error");
LicenseItems = new();
IsEnabled = false;
UpdateWindow();
}
}
private void UpdateWindow()
{
// Always a minimum of one license required!
Licenses = Math.Max(1, LicenseItems.OrderByDescending(x => x.Users).FirstOrDefault()?.Users ?? 0);
Modules.Items = LicenseItems;
Modules.Refresh(true, true);
var lookups = new RenewalPeriodLookups(null).AsTable("RenewalPeriod");
RenewalPeriodEditor.LoadLookups(lookups);
RenewalPeriodEditor.Loaded = true;
RenewalPeriod = LicenseUtils.TimeDiscountLevels().OrderBy(x => x).FirstOrDefault();
PayWithStripe.IsEnabled = CanRenew;
if (!PayWithStripe.IsEnabled)
{
PayTooltip.Visibility = Visibility.Visible;
PayTooltip.Content = new Label { Content = $"Renewal available from {RenewalAvailableFrom:dd MMM yyyy}" };
}
else
PayTooltip.Visibility = Visibility.Collapsed;
LastRenewal.Loaded = true;
CurrentExpiry.Loaded = true;
NewExpiry.Loaded = true;
//PayWithStripe.IsEnabled = false;
PayTooltip.Visibility = Visibility.Visible;
PayTooltip.Content = new Label { Content = "Loading..." };
LastRenewal.Value = CurrentLicense?.LastRenewal ?? DateTime.MinValue;
CurrentExpiry.Value = CurrentLicense?.Expiry ?? DateTime.MinValue;
RenewalAvailableFrom = CurrentLicense?.RenewalAvailable ?? DateTime.MinValue;
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
LoadData();
}
private void RetrieveFees()
{
var summary = LicenseClient.PostRequest(
new LicenseFeeRequest() { RegistrationID = CurrentLicense?.CustomerID ?? Guid.Empty },
nameof(LicenseFeeRequest)
);
LicenseUtils.LoadSummary(summary);
}
private void LoadUserTracking()
{
var renewaldate = _currentLicense?.LastRenewal ?? DateTime.MinValue;
var filter = !renewaldate.IsEmpty()
? new Filter(x => x.Date).IsGreaterThanOrEqualTo(renewaldate).And(x => x.TotalWrite).IsNotEqualTo(0)
: new Filter(x => x.TotalWrite).IsNotEqualTo(0);
var data = new Client()
.Query(
filter,
InABox.Core.Columns.None().Add(x => x.User.ID)
.Add(x => x.Type));
var typesummary = data.Rows.GroupBy(r => r.Get(c => c.Type)).ToArray();
//Licenses = data.ExtractValues(x => x.User.ID).Distinct().Count();
var licensemap = LicenseUtils.LicenseMap();
var result = new List();
foreach (var map in licensemap)
{
var type = map.Value.EntityName();
var item = result.FirstOrDefault(x => Equals(x.Type, type));
if (item == null)
{
item = new LicenseTrackingItem()
{
Type = type,
Caption = map.Value.GetCaption(),
};
result.Add(item);
}
var users = typesummary
.FirstOrDefault(x => Equals(x.Key, map.Key.EntityName().Split('.').Last()))?
.Select(r=>r.Get(x=>x.User.ID))
.Distinct()
.Where(x=>!item.UserIDs.Contains(x));
if (users != null)
item.UserIDs.AddRange(users);
}
LicenseItems = result
.OrderBy(x=>x.Caption)
.ToList();
}
private static LicenseData? LoadCurrentLicense()
{
var license = new Client().Query(
new Filter().All(),
InABox.Core.Columns.None().Add(x => x.Data))
.Rows.FirstOrDefault()?.ToObject();
if(license == null)
{
MessageBox.Show("No current license found. Please see the documentation on how to proceed.");
return null;
}
if(!LicenseUtils.TryDecryptLicense(license.Data, out var data, out var error))
{
MessageBox.Show("Current license is corrupt. Please see the documentation on how to proceed.");
return null;
}
return data;
}
private void RenewalPeriod_OnEditorValueChanged(IDynamicEditorControl sender, Dictionary values)
{
CalculateDiscounts();
}
private void CalculateDiscounts()
{
double CalcDiscount(double amount, int months)
{
return (amount * (LicenseUtils.GetUserDiscount(Licenses) / 100.0F)) +
(amount * (LicenseUtils.GetTimeDiscount(months) / 100.0F));
}
var periodInMonths = RenewalPeriod;
NewExpiry.Value = NewExpiration;
double total = 0.0F;
if (CurrentLicense?.IsDynamic == true)
{
foreach (var row in Modules.Data.Rows)
total += row.Get(x => x.ExGST) * periodInMonths;
Gross = total;
Discount = CalcDiscount(total, periodInMonths);
}
else
{
foreach (var row in Modules.Data.Rows)
total += Licenses * LicenseUtils.GetLicenseFee(row.Get(x => x.Type)) * periodInMonths;
Gross = Math.Round(total) - 0.05;
Gross = total;
Discount = Math.Round(CalcDiscount(total, periodInMonths) * 20F) / 20F;
}
GrossLicenseFee.Value = Gross;
DiscountEditor.Value = Discount;
NettLicenseFee.Value = Net;
PayWithStripe.IsEnabled = CanRenew && Net > 0;
}
private class RenewalPeriodLookups : LookupGenerator