using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Billing.Languages; using Billing.Models; using Billing.UI; using Xamarin.Forms; namespace Billing.Views { public partial class AccountPage : BillingPage { private static readonly BindableProperty BalanceProperty = BindableProperty.Create(nameof(Balance), typeof(decimal), typeof(AccountPage)); private static readonly BindableProperty AssetProperty = BindableProperty.Create(nameof(Asset), typeof(decimal), typeof(AccountPage)); private static readonly BindableProperty LiabilityProperty = BindableProperty.Create(nameof(Liability), typeof(decimal), typeof(AccountPage)); private static readonly BindableProperty AccountsProperty = BindableProperty.Create(nameof(Accounts), typeof(List), typeof(AccountPage)); public decimal Balance => (decimal)GetValue(BalanceProperty); public decimal Asset => (decimal)GetValue(AssetProperty); public decimal Liability => (decimal)GetValue(LiabilityProperty); public List Accounts => (List)GetValue(AccountsProperty); public Command EditAccount { get; } public Command DeleteAccount { get; } private readonly List accounts = new(); private bool initialized; public AccountPage() { EditAccount = new Command(OnEditAccount); DeleteAccount = new Command(OnDeleteAccount); SetValue(AccountsProperty, accounts); InitializeComponent(); } protected override void OnAppearing() { if (!initialized || accounts.Count == 0) { initialized = true; accounts.Clear(); foreach (var account in App.Accounts) { account.Balance = account.Initial + App.Bills.Where(b => b.WalletId == account.Id).Sum(b => b.Amount); AddToAccountGroup(account); } } else { foreach (var account in App.Accounts) { account.Balance = account.Initial + App.Bills.Where(b => b.WalletId == account.Id).Sum(b => b.Amount); } } groupLayout.Refresh(accounts); RefreshBalance(); } private void RefreshBalance() { SetValue(BalanceProperty, App.Accounts.Sum(a => a.Balance)); } private void AddToAccountGroup(Account account) { int maxId; if (accounts.Count > 0) { maxId = accounts.Max(g => g.Max(a => a.Id)); } else { maxId = -1; } account.Id = maxId + 1; var group = accounts.FirstOrDefault(g => g.Key == account.Category); if (group == null) { group = new AccountGrouping(account.Category, account.Balance) { account }; accounts.Add(group); } else { group.Add(account); group.Balance += account.Balance; } } private async void OnEditAccount(object o) { if (Tap.IsBusy) { return; } using (Tap.Start()) { var page = new AddAccountPage(o as Account); page.AccountChecked += AccountChecked; await Navigation.PushAsync(page); } } private async void OnDeleteAccount(object o) { if (Tap.IsBusy) { return; } using (Tap.Start()) { if (o is Account account) { var result = await this.ShowConfirm(Resource.ConfirmDeleteAccount); if (result) { App.Accounts.Remove(account); var group = accounts.FirstOrDefault(a => a.Key == account.Category); if (group == null) { Helper.Error("account.delete", "unexpected deleting account, cannot find the current category"); return; } group.Remove(account); if (group.Count == 0) { accounts.Remove(group); } groupLayout.Refresh(accounts); RefreshBalance(); _ = Task.Run(App.WriteAccounts); } } } } private void AccountChecked(object sender, AccountEventArgs e) { if (e.Account.Id < 0) { App.Accounts.Add(e.Account); AddToAccountGroup(e.Account); } groupLayout.Refresh(accounts); RefreshBalance(); Task.Run(App.WriteAccounts); } } public class AccountGrouping : List, IGrouping { public AccountCategory Key { get; } public decimal Balance { get; set; } public AccountGrouping(AccountCategory key, decimal balance) : base() { Key = key; Balance = balance; } } }