using System; using System.ComponentModel; using System.Threading.Tasks; using Serilog; using TINK.Model; using TINK.Model.Bikes; using TINK.Model.Connector; using TINK.Model.Services.CopriApi; using TINK.ViewModel.Info; using Xamarin.Forms; namespace TINK.ViewModel.Contact { public class FeesAndBikesPageViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; /// Holds value wether site caching is on or off. bool IsSiteCachingOn { get; } /// /// Relative path to fees resources of empty if value was not yet querried from backend. /// private string FeesResourcePath { get; set; } /// /// Relative path to bike info resources of empty if value was not yet querried from backend. /// private string BikesResourcePath { get; set; } private bool _IsIdle = false; /// /// Is true if no action is pending, false otherwise. /// public bool IsIdle { get => _IsIdle; private set { if (_IsIdle == value) { // Nothing to do. return; } _IsIdle = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(IsIdle))); return; } } /// /// Object to querry resources urls object from backend if required. /// This object is used to update resources path values , and from. /// private Func QueryProvider { get; } /// /// Action to update shared resources urls object exposed by main model. /// private Action UpdateUrlsAction { get; } /// Constructs view model. /// Set of user permissions /// Delegate to get an an embedded html ressource. Used as fallback if download from web page does not work and cache is empty. /// Object to querry resources path values if required. public FeesAndBikesPageViewModel( string hostName, string feesResourcePath, string bikesResourcePath, bool isSiteCachingOn, Func queryProvider, Action updateUrlsAction) { HostName = hostName; FeesResourcePath = feesResourcePath; BikesResourcePath = bikesResourcePath; IsSiteCachingOn = isSiteCachingOn; QueryProvider = queryProvider; UpdateUrlsAction = updateUrlsAction; } /// Holds the name of the host. private string HostName { get; } /// Called when page is shown. public async void OnAppearing() { // Get resource urls object from backend. async Task GetUrls() { Result bikes; try { bikes = await QueryProvider().GetBikesAsync(); } catch (Exception ex) { Log.ForContext().Error($"Getting resource urls from COPRI failed. {ex.Message}"); return new ResourceUrls(); } return bikes?.GeneralData?.ResourceUrls ?? new ResourceUrls(); } // Set state to busy. IsIdle = false; if (string.IsNullOrEmpty(FeesResourcePath)) { var urls = await GetUrls(); FeesResourcePath = urls.FeesResourcePath; BikesResourcePath = urls.BikesResourcePath; UpdateUrlsAction(urls); // Update main model to prevent duplicate queries. } RentBikeText = new HtmlWebViewSource { Html = !string.IsNullOrEmpty(FeesResourcePath) ? await ViewModelHelper.GetSource($"https://{HostName}/{FeesResourcePath}", IsSiteCachingOn) : await Task.FromResult(ViewModelHelper.FromBody("No fees resource available. Resource path is null or empty.")) }; TypesOfBikesText = new HtmlWebViewSource { Html = !string.IsNullOrEmpty(BikesResourcePath) ? await ViewModelHelper.GetSource($"https://{HostName}/{BikesResourcePath}" /*"site/bike_info.html"*/, IsSiteCachingOn) : await Task.FromResult(ViewModelHelper.FromBody("No bikes instruction resource available. Resource path is null or empty.")) }; // Set state to idle. IsIdle = true; } private HtmlWebViewSource rentBikeText; private HtmlWebViewSource typesOfBikesText; public HtmlWebViewSource RentBikeText { get => rentBikeText; set { rentBikeText = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(RentBikeText))); } } public HtmlWebViewSource TypesOfBikesText { get => typesOfBikesText; set { typesOfBikesText = value; PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(TypesOfBikesText))); } } } }