using Billing.Models; using Billing.UI; using Billing.Views; using System; using System.Globalization; using System.Linq; using System.Runtime.CompilerServices; using System.Threading.Tasks; using Xamarin.Essentials; using Xamarin.Forms; namespace Billing { internal static class Helper { #if DEBUG public static void Debug(string message) { var time = DateTime.Now.ToString("HH:mm:ss.fff"); System.Diagnostics.Debug.WriteLine($"[{time}] - {message}"); } #else #pragma warning disable IDE0060 // Remove unused parameter public static void Debug(string message) { } #pragma warning restore IDE0060 // Remove unused parameter #endif public static void Error(string category, Exception ex) { Error(category, ex?.ToString() ?? "unknown error"); } public static void Error(string category, string message) { #if DEBUG var time = DateTime.Now.ToString("HH:mm:ss.fff"); System.Diagnostics.Debug.WriteLine($"[{time}] - {category}", message); MainThread.BeginInvokeOnMainThread(async () => await Shell.Current.DisplayAlert(category, message, "Ok")); #endif _ = Store.StoreHelper.SaveLogItemAsync(new Logs() { LogTime = DateTime.Now, Category = category, Detail = message }); } public static bool NetworkAvailable { get { try { return Connectivity.NetworkAccess == NetworkAccess.Internet || Connectivity.NetworkAccess == NetworkAccess.ConstrainedInternet; } catch { return false; } } } public const string DEFAULT_COLOR = "#183153"; public static string WrapColorString(string color) { if (color == null) { return DEFAULT_COLOR; } if (color.Length > 7) { var alpha = color[1..3]; if (int.TryParse(alpha, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out int a) && a == 255) { return "#" + color[3..]; } } return color; } public static UIBill WrapBill(Bill b) { var category = App.Categories.FirstOrDefault(c => c.Id == b.CategoryId); return new UIBill(b) { Icon = category?.Icon ?? Definition.DefaultIcon, TintColor = category?.TintColor ?? Definition.TransparentColor, Name = b.Name, DateCreation = b.CreateTime, Amount = b.Amount, Wallet = App.Accounts.FirstOrDefault(a => a.Id == b.WalletId)?.Name }; } public static bool IsSameDay(DateTime day1, DateTime day2) { return day1.Year == day2.Year && day1.DayOfYear == day2.DayOfYear; } public static DateTime FirstDay(DateTime date) { var week = date.DayOfWeek; if (week == DayOfWeek.Sunday) { return date; } return date.AddDays(-(int)week); } public static BindableProperty Create(string name, TResult defaultValue = default, PropertyValueChanged propertyChanged = null) where TOwner : BindableObject { if (propertyChanged == null) { return BindableProperty.Create(name, typeof(TResult), typeof(TOwner), defaultValue: defaultValue); } return BindableProperty.Create(name, typeof(TResult), typeof(TOwner), defaultValue: defaultValue, propertyChanged: (obj, old, @new) => { if (old != null && !(old is TResult)) { return; } if (@new != null && !(@new is TResult)) { return; } propertyChanged((TOwner)obj, (TResult)old, (TResult)@new); }); } public delegate void PropertyValueChanged(TOwner obj, TResult old, TResult @new); public static async Task CheckAndRequestPermissionAsync() where T : Permissions.BasePermission, new() { var status = await Permissions.CheckStatusAsync(); if (status != PermissionStatus.Disabled && status != PermissionStatus.Granted) { status = await Permissions.RequestAsync(); } return status; } private static double TransformLatitude(double x, double y) { var ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.Sqrt(Math.Abs(x)); ret += (20.0 * Math.Sin(6.0 * x * Math.PI) + 20.0 * Math.Sin(2.0 * x * Math.PI)) * 2.0 / 3.0; ret += (20.0 * Math.Sin(y * Math.PI) + 40.0 * Math.Sin(y / 3.0 * Math.PI)) * 2.0 / 3.0; ret += (160.0 * Math.Sin(y / 12.0 * Math.PI) + 320 * Math.Sin(y * Math.PI / 30.0)) * 2.0 / 3.0; return ret; } private static double TransformLongitude(double x, double y) { var ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.Sqrt(Math.Abs(x)); ret += (20.0 * Math.Sin(6.0 * x * Math.PI) + 20.0 * Math.Sin(2.0 * x * Math.PI)) * 2.0 / 3.0; ret += (20.0 * Math.Sin(x * Math.PI) + 40.0 * Math.Sin(x / 3.0 * Math.PI)) * 2.0 / 3.0; ret += (150.0 * Math.Sin(x / 12.0 * Math.PI) + 300.0 * Math.Sin(x / 30.0 * Math.PI)) * 2.0 / 3.0; return ret; } public static (double longitude, double latitude) Wgs84ToGcj02(double longitude, double latitude) { var a = 6378245.0; var ee = 0.00669342162296594323; var offsetLatitude = TransformLatitude(longitude - 105.0, latitude - 35.0); var offsetLongitude = TransformLongitude(longitude - 105.0, latitude - 35.0); var radiusLatitude = latitude / 180.0 * Math.PI; var magic = Math.Sin(radiusLatitude); magic = 1 - ee * magic * magic; var sqrtMagic = Math.Sqrt(magic); offsetLatitude = offsetLatitude * 180.0 / (a * (1 - ee) / (magic * sqrtMagic) * Math.PI); offsetLongitude = offsetLongitude * 180.0 / (a / sqrtMagic * Math.Cos(radiusLatitude) * Math.PI); return (longitude + offsetLongitude, latitude + offsetLatitude); } } public class AsyncLazy { private readonly Lazy> instance; public AsyncLazy(Func> factory) { instance = new Lazy>(() => Task.Run(factory)); } public TaskAwaiter GetAwaiter() { return instance.Value.GetAwaiter(); } } }