using Plugin.Messaging;
using Serilog;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows.Input;
using TINK.Model.Services.CopriApi.ServerUris;
using TINK.Model.Station;
using TINK.MultilingualResources;
using TINK.View;
using Xamarin.Essentials;
using Xamarin.Forms;
namespace TINK.ViewModel.Info
{
/// View model for contact page.
public class ContactPageViewModel
{
/// Reference on view service to show modal notifications and to perform navigation.
private IViewService ViewService { get; }
/// Station selected by user.
private IStation SelectedStation;
Uri ActiveUri { get; }
/// Holds a reference to the external trigger service.
private Action OpenUrlInExternalBrowser { get; }
Func CreateAttachment { get; }
/// Constructs a contact page view model.
/// Action to open an external browser.
/// View service to notify user.
public ContactPageViewModel(
IStation selectedStation,
Uri activeUri,
Func createAttachment,
Action openUrlInExternalBrowser,
IViewService viewService)
{
ActiveUri = activeUri
?? throw new ArgumentException("Can not instantiate contact page view model- object. No active uri available.");
CreateAttachment = createAttachment
?? throw new ArgumentException("Can not instantiate contact page view model- object. No create attachment provider available.");
ViewService = viewService
?? throw new ArgumentException("Can not instantiate contact page view model- object. No user view service available.");
OpenUrlInExternalBrowser = openUrlInExternalBrowser
?? throw new ArgumentException("Can not instantiate contact page view model- object. No user external browse service available.");
// Station might be null-station, if no station info is avialable.
SelectedStation = selectedStation;
}
/// Command object to bind login button to view model.
public ICommand OnMailRequest
=> new Command(
async () => await DoSendMail(),
() => IsSendMailAvailable);
/// True if sending mail is possible.
public bool IsSendMailAvailable =>
CrossMessaging.Current.EmailMessenger.CanSendEmail;
/// cTrue if doing a phone call is possible.
public bool IsDoPhoncallAvailable
=> CrossMessaging.Current.PhoneDialer.CanMakePhoneCall;
/// Holds the mail address to mail to.
public string MailAddressText
=> SelectedStation?.OperatorData?.MailAddressText ?? string.Empty;
/// Holds the mail address to send mail to.
public string PhoneNumberText
=> SelectedStation?.OperatorData?.PhoneNumberText ?? string.Empty;
/// Holds the mail address to send mail to.
public string OfficeHoursText
=> SelectedStation?.OperatorData?.Hours ?? string.Empty;
/// Gets whether any operator support info is avaliable.
public bool IsOperatorInfoAvaliable
=> MailAddressText.Length > 0 || PhoneNumberText.Length > 0;
/// Request to do a phone call.
public async Task DoSendMail()
{
try
{
if (!IsSendMailAvailable)
{
// Nothing to do because email can not be sent.
return;
}
var tinkMail = await ViewService.DisplayAlert(
AppResources.QuestionTitle,
string.Format(AppResources.QuestionSupportmailSubject, GetAppName(ActiveUri)),
string.Format(AppResources.QuestionSupportmailAnswerOperator, GetAppName(ActiveUri)),
string.Format(AppResources.QuestionSupportmailAnswerApp, GetAppName(ActiveUri)));
if (tinkMail)
{
// Send TINK- related support mail.
await Email.ComposeAsync(new EmailMessage { To = new List { MailAddressText }, Subject = $"{GetAppName(ActiveUri)} Anfrage" });
return;
}
// Send a tink app related mail
var appendFile = false;
appendFile = await ViewService.DisplayAlert(
AppResources.QuestionTitle,
AppResources.QuestionSupportmailAttachment,
AppResources.QuestionAnswerYes,
AppResources.QuestionAnswerNo);
var message = new EmailMessage { To = new List { MailAddressText }, Subject = $"{GetAppName(ActiveUri)}-App Anfrage" };
if (appendFile == false)
{
// Send a tink app related mail
await Email.ComposeAsync(message);
return;
}
var logFileName = string.Empty;
try
{
logFileName = CreateAttachment();
}
catch (Exception l_oException)
{
await ViewService.DisplayAdvancedAlert(
AppResources.MessageWaring,
AppResources.ErrorSupportmailCreateAttachment,
l_oException.Message,
AppResources.MessageAnswerOk);
Log.Error("An error occurred creating attachment. {@l_oException)", l_oException);
}
if (!string.IsNullOrEmpty(logFileName))
{
message.Attachments.Add(new Xamarin.Essentials.EmailAttachment(logFileName));
}
// Send a tink app related mail
await Email.ComposeAsync(message);
}
catch (Exception p_oException)
{
Log.Error("An unexpected error occurred sending mail. {@Exception}", p_oException);
await ViewService.DisplayAdvancedAlert(
AppResources.MessageWaring,
AppResources.ErrorSupportmailMailingFailed,
p_oException.Message,
AppResources.MessageAnswerOk);
return;
}
}
/// Command object to bind login button to view model.
public ICommand OnSelectStationRequest
#if USEMASTERDETAIL || USEFLYOUT
=> new Xamarin.Forms.Command(() => OpenSelectStationPage());
#else
=> new Xamarin.Forms.Command(async () => await OpenSelectStationPageAsync());
#endif
/// Opens login page.
#if USEMASTERDETAIL || USEFLYOUT
public void OpenSelectStationPage()
#else
public async Task OpenSelectStationPageAsync()
#endif
{
try
{
// Switch to map page
#if USEMASTERDETAIL || USEFLYOUT
ViewService.PushAsync(ViewTypes.SelectStationPage);
#else
await ViewService.ShowPage("//SelectStationPage");
#endif
}
catch (Exception p_oException)
{
Log.Error("Ein unerwarteter Fehler ist in der Klasse ContactPageViewModel aufgetreten. Kontext: Klick auf Hinweistext auf Station N- seite ohne Anmeldung. {@Exception}", p_oException);
return;
}
}
/// Command object to bind phone call button.
public ICommand OnPhoneRequest
=> new Command(
async () => await DoPhoneCall(),
() => IsDoPhoncallAvailable);
/// Request to do a phone call.
public async Task DoPhoneCall()
{
try
{
// Make Phone Call
if (IsDoPhoncallAvailable)
{
CrossMessaging.Current.PhoneDialer.MakePhoneCall(PhoneNumberText);
}
}
catch (Exception p_oException)
{
Log.Error("An unexpected error occurred doing a phone call. {@Exception}", p_oException);
await ViewService.DisplayAdvancedAlert(
AppResources.MessageWaring,
AppResources.ErrorSupportmailPhoningFailed,
p_oException.Message,
AppResources.MessageAnswerOk);
return;
}
}
/// Text providing mail address and possilbe reasons to contact.
public string ProviderNameText
=> string.Format("Betreiber: {0}", SelectedStation?.OperatorData?.Name)
;
/// Text providing mail address and possilbe reasons to contact.
public FormattedString MailAddressAndMotivationsText
{
get
{
var hint = new FormattedString();
hint.Spans.Add(new Span { Text = AppResources.MessageContactMail });
return hint;
}
}
/// Invitation to rate app.
public FormattedString LikeTinkApp
{
get
{
var l_oHint = new FormattedString();
l_oHint.Spans.Add(new Span { Text = string.Format(AppResources.MessageRateMail, GetAppName(ActiveUri)) });
return l_oHint;
}
}
/// User clicks rate button.
public ICommand OnRateRequest
=> new Command(() => RegisterRequest());
/// Opens login page.
public void RegisterRequest()
{
try
{
OpenUrlInExternalBrowser();
}
catch (Exception p_oException)
{
Log.Error("Ein unerwarteter Fehler ist auf der Login Seite beim Öffnen eines Browsers, Seite {url}, aufgetreten. {@Exception}", p_oException);
return;
}
}
/// Invitation to rate app.
public FormattedString PhoneContactText
{
get
{
var l_oHint = new FormattedString();
l_oHint.Spans.Add(new Span
{
Text = string.Format(AppResources.MessagePhoneMail, GetAppName(ActiveUri)) + $"{(OfficeHoursText.Length > 0 ? $" {OfficeHoursText}" : string.Empty)}"
});
return l_oHint;
}
}
/// Gets the application name.
public static string GetAppName(Uri activeUri)
{
switch (activeUri.AbsoluteUri)
{
case CopriServerUriList.TINK_DEVEL:
case CopriServerUriList.TINK_LIVE:
return "TINK";
case CopriServerUriList.SHAREE_DEVEL:
case CopriServerUriList.SHAREE_LIVE:
return "sharee.bike";
default:
return "Teilrad";
}
}
}
}