using MonkeyCache.FileStore;
using Serilog;
using System;
using System.Threading.Tasks;
using TINK.Repository.Exception;
using TINK.Model.Device;
using TINK.Model.State;
using TINK.Model.Station;
using TINK.Model.User;
using Xamarin.Forms;
using TINK.Model.Bikes.Bike.BC;
using TINK.Repository;
using System.Net;
using TINK.MultilingualResources;
using System.Linq;
namespace TINK.ViewModel
{
public static class ViewModelHelper
{
/// First part of text making up a station name.
private const string USER_FIENDLY_STATIONNUMBER_PREFIX = "Station";
/// Holds the color which marks link to TINK- app pages, web sites, ...
public static Color LINK_COLOR = Color.Blue;
///
/// Gets station name from station object.
///
/// Station to get id from
///
public static string GetStationName(this IStation station)
{
if (station == null)
{
return string.Empty;
}
if (!string.IsNullOrEmpty(station.StationName))
{
return $"{station.StationName}, Nr. {station.Id}.";
}
return GetStationName(station.Id);
}
///
/// Gets station name from station object.
///
/// Station to get id from
///
public static string GetStationName(string station)
{
return string.Format("{0} {1}", USER_FIENDLY_STATIONNUMBER_PREFIX, station);
}
///
/// Gets station id from station name.
///
/// Station to get id from
///
public static int GetStationId(string stationName)
{
return int.Parse(stationName.Replace(USER_FIENDLY_STATIONNUMBER_PREFIX, "").Trim());
}
/// Get full display name of a bike which includes id.
///
/// If name is empty return Id as name.
///
/// bike to get name for.
/// Display name of bike.
public static string GetFullDisplayName(this IBikeInfoMutable bike)
=> $"{(!string.IsNullOrEmpty(bike.Description) ? $"{bike.Description}, " : string.Empty)}Nr. {bike.Id}";
/// Get the display name of a bike.
/// bike to get name for.
/// Display name of bike.
public static string GetDisplayName(this IBikeInfoMutable bike)
=> $"{(!string.IsNullOrEmpty(bike.Description) ? $"{bike.Description}" : $"{bike.Id}")}";
/// Get the display id of a bike.
///
/// If name is empty id is used as name. For this reason return nothing in this case to avoid duplicate output of id.
///
/// bike to get name for.
/// Display name of bike.
public static string GetDisplayId(this IBikeInfoMutable bike)
=> $"{(!string.IsNullOrEmpty(bike.Description) ? $"{bike.Id}" : string.Empty)}";
///
/// Maps state to color.
///
///
///
public static Color GetColor(this InUseStateEnum state)
{
switch (state)
{
case InUseStateEnum.Disposable:
return Color.Default;
case InUseStateEnum.Reserved:
return Color.Orange;
case InUseStateEnum.Booked:
return Color.Green;
default:
return Color.Default;
}
}
/// Gets message that logged in user has not booked any bikes.
/// Holds whether report level is verbose or not.
public static string GetShortErrorInfoText(this Exception exception, bool isReportLevelVerbose)
{
if (exception == null)
{
return string.Empty;
}
if (exception is AuthcookieNotDefinedException)
return AppResources.ActivityTextAuthcookieNotDefinedException;
if (!isReportLevelVerbose)
{
return AppResources.ActivityTextException;
}
// An error occurred getting bikes information.
#if USCSHARP9
switch (exception)
{
case WebConnectFailureException:
return AppResources.ActivityTextErrorWebConnectFailureException;
case InvalidResponseException:
return AppResources.ActivityTextErrorInvalidResponseException;
case WebForbiddenException:
return AppResources.ActivityTextErrorWebForbiddenException;
case DeserializationException:
return AppResources.ActivityTextErrorDeserializationException;
case WebException webException:
return webException.Status == WebExceptionStatus.ProtocolError && webException.Response is HttpWebResponse webResponse
? string.Format(AppResources.ActivityTextErrorWebExceptionProtocolError, webResponse.StatusDescription)
: string.Format(AppResources.ActivityTextErrorWebExceptionGeneralError, webException.Status.ToString());
default:
return AppResources.ActivityTextErrorException;
}
#else
if (exception is WebConnectFailureException)
return AppResources.ActivityTextErrorWebConnectFailureException;
if (exception is InvalidResponseException)
return AppResources.ActivityTextErrorInvalidResponseException;
if (exception is WebForbiddenException)
return AppResources.ActivityTextErrorWebForbiddenException;
if (exception is DeserializationException)
return AppResources.ActivityTextErrorDeserializationException;
if (exception is WebException webException)
{
return webException.Status == WebExceptionStatus.ProtocolError && webException.Response is HttpWebResponse webResponse
? string.Format(AppResources.ActivityTextErrorWebExceptionProtocolError, webResponse.StatusDescription)
: string.Format(AppResources.ActivityTextErrorWebExceptionGeneralError, webException.Status.ToString());
}
return AppResources.ActivityTextErrorException;
#endif
}
/// Gets error message and handles aggegate exceptions.
public static string GetErrorMessage(this Exception exception)
{
if (exception == null)
return string.Empty;
if (!(exception is AggregateException aggregateException))
return exception.Message;
if (aggregateException.InnerExceptions.Count == 1)
return aggregateException.InnerExceptions[0].Message;
return new AggregateException().Message + "\r\n"+ string.Join("\r\n", aggregateException.InnerExceptions.Select(x => x.Message));
}
/// Gets message that logged in user has not booked any bikes.
public static FormattedString GetErrorInfoText(this Exception exception)
{
if (exception == null)
{
return string.Empty;
}
FormattedString l_oError;
// An error occurred getting bikes information.
if (exception is WebConnectFailureException)
{
l_oError = new FormattedString();
l_oError.Spans.Add(new Span { Text = "Information!\r\n", FontAttributes = FontAttributes.Bold });
l_oError.Spans.Add(new Span { Text = $"{exception.Message}\r\n{WebConnectFailureException.GetHintToPossibleExceptionsReasons}" });
return l_oError;
}
else if (exception is InvalidResponseException)
{
l_oError = new FormattedString();
l_oError.Spans.Add(new Span { Text = "Fehler, ungültige Serverantwort!\r\n", FontAttributes = FontAttributes.Bold });
l_oError.Spans.Add(new Span { Text = $"{exception.Message}" });
return l_oError;
}
else if (exception is WebForbiddenException)
{
l_oError = new FormattedString();
l_oError.Spans.Add(new Span { Text = "Beschäftigt... Einen Moment bitte!" });
return l_oError;
}
l_oError = new FormattedString();
l_oError.Spans.Add(new Span { Text = "Allgemeiner Fehler!\r\n", FontAttributes = FontAttributes.Bold });
l_oError.Spans.Add(new Span { Text = $"{exception}" });
return l_oError;
}
/// User tabbed a URI.
/// Sender of the event.
/// Event arguments
public static void OnNavigating(object sender, WebNavigatingEventArgs eventArgs)
{
if (!eventArgs.Url.ToUpper().StartsWith("HTTP"))
{
// An internal link was detected.
// Stay inside WebView
eventArgs.Cancel = false;
return;
}
// Do not navigate outside the document.
eventArgs.Cancel = true;
DependencyService.Get().OpenUrl(eventArgs.Url);
}
/// Gets the user group if a user friendly name.
///
///
public static string GetUserGroupDisplayName(this User user)
{
return string.Join(" & ", user.Group);
}
/// Called when page is shown.
/// Url to load data from.
/// Holds value wether site caching is on or off.
/// Provides resource from embedded ressources.
public static async Task GetSource(
string resourceUrl,
bool isSiteCachingOn,
Func resourceProvider = null)
{
if (!Barrel.Current.IsExpired(resourceUrl) && isSiteCachingOn)
{
// Cached html is still valid and caching is on.
return Barrel.Current.Get(resourceUrl);
}
string htmlContent = string.Empty;
try
{
// Get info from web server.
htmlContent = await CopriCallsHttps.Get(resourceUrl);
}
catch (Exception l_oException)
{
// Getting html failed.
Log.Error($"Requesting {resourceUrl} failed. {l_oException.Message}");
}
switch (string.IsNullOrEmpty(htmlContent))
{
case true:
// An error occurred getting resource from web
htmlContent = Barrel.Current.Exists(resourceUrl)
? Barrel.Current.Get(key: resourceUrl) // Get from MonkeyCache
: resourceProvider != null ? resourceProvider() : $"Error loading {resourceUrl}."; // Get build in ressource.
break;
default:
// Add resource to cache.
Barrel.Current.Add(key: resourceUrl, data: htmlContent, expireIn: isSiteCachingOn ? TimeSpan.FromDays(1) : TimeSpan.FromMilliseconds(1) );
break;
}
return htmlContent ?? FromBody("An error occurred loading html- ressource.");
}
public static string FromBody(string message) => $"Error Information{message}";
}
}