import 'package:core/data/model/query/query_parameter.dart'; import 'package:core/data/network/config/service_path.dart'; import 'package:core/utils/app_logger.dart'; import 'package:core/utils/platform_info.dart'; import 'package:get/get.dart'; import 'package:jmap_dart_client/jmap/core/id.dart'; import 'package:jmap_dart_client/jmap/mail/email/email.dart'; import 'package:jmap_dart_client/jmap/mail/email/email_address.dart'; import 'package:jmap_dart_client/jmap/mail/mailbox/mailbox.dart'; import 'package:tmail_ui_user/features/login/data/extensions/service_path_extension.dart'; import 'package:tmail_ui_user/features/manage_account/presentation/model/account_menu_item.dart'; import 'package:tmail_ui_user/features/thread/domain/model/search_query.dart'; import 'package:tmail_ui_user/main/routes/app_routes.dart'; import 'package:tmail_ui_user/main/routes/navigation_router.dart'; import 'package:universal_html/html.dart' as html; abstract class RouteUtils { static const String paramID = 'id'; static const String paramType = 'type'; static const String paramContext = 'context'; static const String paramQuery = 'q'; static const String paramRouteName = 'routeName'; static const String paramMailtoAddress = 'mailtoAddress'; static const String paramSubject = 'subject'; static const String paramBody = 'body'; static const String paramTo = 'to'; static const String paramCc = 'cc'; static const String paramBcc = 'bcc'; static const String mailtoPrefix = 'mailto'; static const String uriPrefix = 'uri'; static const String ADDRESS_SEPARATOR = ','; static const String INVALID_VALUE = 'invalid'; static String get baseOriginUrl => Uri.base.origin; static Uri get baseUri => Uri.base; static String generateNavigationRoute(String route, {NavigationRouter? router}) { if (PlatformInfo.isWeb) { if (route == AppRoutes.dashboard) { return _createDashboardServicePath(route, router: router).path; } else if (route == AppRoutes.settings) { return _createSettingServicePath(route, router: router).path; } else { return _createServicePath(route).path; } } else { return route; } } static ServicePath _createDashboardServicePath(String route, {NavigationRouter? router}) { ServicePath servicePath = ServicePath(route); if (router != null) { if (router.emailId != null) { servicePath = servicePath.withPathParameter(router.emailId!.id.value); } servicePath = servicePath.withQueryParameters([ StringQueryParameter(paramType, router.dashboardType.name), if (router.mailboxId != null) StringQueryParameter(paramContext, router.mailboxId!.id.value), if (router.searchQuery != null) StringQueryParameter(paramQuery, router.searchQuery!.value), ]); } else { servicePath = servicePath.withQueryParameters([ StringQueryParameter(paramType, DashboardType.normal.name) ]); } return servicePath; } static ServicePath _createSettingServicePath(String route, {NavigationRouter? router}) { ServicePath servicePath = ServicePath(route); if (router != null && router.accountMenuItem != AccountMenuItem.none) { servicePath = servicePath.withQueryParameters([ StringQueryParameter(paramType, router.accountMenuItem.getAliasBrowser()) ]); } return servicePath; } static ServicePath _createEmailEMLPreviewerServicePath(String route, {String? previewId}) { ServicePath servicePath = ServicePath(route); if (previewId?.trim().isNotEmpty == true) { servicePath = servicePath.withQueryParameters([ StringQueryParameter(paramID, previewId!) ]); } return servicePath; } static ServicePath _createServicePath(String route) { ServicePath servicePath = ServicePath(route); return servicePath; } static Uri createUrlWebLocationBar(String route, {NavigationRouter? router, String? previewId}) { if (route == AppRoutes.dashboard) { final servicePath = _createDashboardServicePath( '$baseOriginUrl$route', router: router ); return Uri.parse(servicePath.path); } else if (route == AppRoutes.settings) { final servicePath = _createSettingServicePath('$baseOriginUrl$route', router: router); return Uri.parse(servicePath.path); } else if (route == AppRoutes.emailEMLPreviewer) { final servicePath = _createEmailEMLPreviewerServicePath( '$baseOriginUrl$route', previewId: previewId, ); return Uri.parse(servicePath.path); } else { final servicePath = _createServicePath('$baseOriginUrl$route'); return Uri.parse(servicePath.path); } } static NavigationRouter parsingRouteParametersToNavigationRouter(Map parameters) { final idParam = parameters[paramID]; final typeParam = parameters[paramType]; final contextPram = parameters[paramContext]; final queryParam = parameters[paramQuery]; final routeName = parameters[paramRouteName]; final mailtoAddress = parameters[paramMailtoAddress]; final mailtoCc = parameters[paramCc]; final mailtoBcc = parameters[paramBcc]; final subject = parameters[paramSubject]; final body = parameters[paramBody]; final emailId = idParam != null ? EmailId(Id(idParam)) : null; final mailboxId = contextPram != null ? MailboxId(Id(contextPram)) : null; final searchQuery = queryParam != null ? SearchQuery(queryParam) : null; final dashboardType = DashboardType.values.firstWhereOrNull((type) => type.name == typeParam) ?? DashboardType.normal; final settingType = AccountMenuItem.values.firstWhereOrNull((type) => type.getAliasBrowser() == typeParam) ?? AccountMenuItem.none; List? listEmailAddress; List? cc; List? bcc; listEmailAddress = _emailAddressesFromMailtoAddress(mailtoAddress); cc = _emailAddressesFromMailtoAddress(mailtoCc); bcc = _emailAddressesFromMailtoAddress(mailtoBcc); log('RouteUtils::parsingRouteParametersToNavigationRouter:listEmailAddress = $listEmailAddress'); return NavigationRouter( emailId: emailId, mailboxId: mailboxId, searchQuery: searchQuery, dashboardType: dashboardType, routeName: routeName, listEmailAddress: listEmailAddress, cc: cc, bcc: bcc, subject: subject, body: body, accountMenuItem: settingType, ); } static List? _emailAddressesFromMailtoAddress(dynamic mailtoAddress) { if (mailtoAddress is List) { return mailtoAddress .map((address) => EmailAddress(null, address)) .toList(); } else if (mailtoAddress is String) { return [ EmailAddress(null, mailtoAddress) ]; } return null; } static void replaceBrowserHistory({required String title, required Uri url}) { log('RouteUtils::replaceBrowserHistory(): title: $title | url: $url'); html.window.history.replaceState(null, title, url.toString()); } static Map parseMapMailtoFromUri(String? mailtoUri) { log('RouteUtils::parseMapMailtoFromUri:mailtoUri: $mailtoUri'); final mapMailto = { RouteUtils.paramRouteName: AppRoutes.mailtoURL, }; mailtoUri = mailtoUri == null ? null : Uri.decodeFull(mailtoUri); final parsedMailToUri = Uri.tryParse(mailtoUri ?? ''); if (parsedMailToUri?.scheme == mailtoPrefix) { final to = { ...?parsedMailToUri?.path.split(ADDRESS_SEPARATOR), ...?parsedMailToUri?.queryParameters[paramTo]?.split(ADDRESS_SEPARATOR) }.toList(); final cc = { ...?parsedMailToUri?.queryParameters[paramCc]?.split(ADDRESS_SEPARATOR), }.toList(); final bcc = { ...?parsedMailToUri?.queryParameters[paramBcc]?.split(ADDRESS_SEPARATOR), }.toList(); final subject = parsedMailToUri?.queryParameters[paramSubject]; final body = parsedMailToUri?.queryParameters[paramBody]; mapMailto[paramMailtoAddress] = to; mapMailto[paramCc] = cc; mapMailto[paramBcc] = bcc; mapMailto[paramSubject] = subject; mapMailto[paramBody] = body; } else if (parsedMailToUri?.path == "/$mailtoPrefix" || parsedMailToUri?.path == "/$mailtoPrefix/") { final uriPrefixQueryParam = parsedMailToUri?.queryParameters[uriPrefix] ?? ''; final uriFromUriPrefixQueryParam = Uri.tryParse(uriPrefixQueryParam); if (uriFromUriPrefixQueryParam?.queryParameters.isNotEmpty == true) { return parseMapMailtoFromUri(mailtoUri?.split('?uri=').last); } final to = { ...?parsedMailToUri?.queryParameters[uriPrefix]?.split('$mailtoPrefix:').last.split(ADDRESS_SEPARATOR), ...?parsedMailToUri?.queryParameters[paramTo]?.split(ADDRESS_SEPARATOR) }.toList(); final cc = { ...?parsedMailToUri?.queryParameters[paramCc]?.split(ADDRESS_SEPARATOR), }.toList(); final bcc = { ...?parsedMailToUri?.queryParameters[paramBcc]?.split(ADDRESS_SEPARATOR), }.toList(); final subject = parsedMailToUri?.queryParameters[paramSubject]; final body = parsedMailToUri?.queryParameters[paramBody]; mapMailto[paramMailtoAddress] = to; mapMailto[paramCc] = cc; mapMailto[paramBcc] = bcc; mapMailto[paramSubject] = subject; mapMailto[paramBody] = body; } else { mapMailto[paramMailtoAddress] = mailtoUri?.split(ADDRESS_SEPARATOR); } if (mapMailto[paramMailtoAddress]?.length == 1) { mapMailto[paramMailtoAddress] = mapMailto[paramMailtoAddress].first; } log('RouteUtils::parseMapMailtoFromUri:paramMailtoAddress = ${mapMailto[paramMailtoAddress]}'); log('RouteUtils::parseMapMailtoFromUri:paramCc = ${mapMailto[paramCc]}'); log('RouteUtils::parseMapMailtoFromUri:paramBcc = ${mapMailto[paramBcc]}'); log('RouteUtils::parseMapMailtoFromUri:paramSubject = ${mapMailto[paramSubject]}'); log('RouteUtils::parseMapMailtoFromUri:paramBody = ${mapMailto[paramBody]}'); return mapMailto; } static NavigationRouter generateNavigationRouterFromMailtoLink(String mailtoLink) { final mailtoMap = parseMapMailtoFromUri(mailtoLink); final navigationRouter = parsingRouteParametersToNavigationRouter(mailtoMap); log('RouteUtils::generateNavigationRouterFromMailtoLink:navigationRouter: $navigationRouter'); return navigationRouter; } static bool canOpenComposerFromNavigationRouter(NavigationRouter navigationRouter) { return navigationRouter.listEmailAddress?.isNotEmpty == true || navigationRouter.cc?.isNotEmpty == true || navigationRouter.bcc?.isNotEmpty == true || navigationRouter.subject?.isNotEmpty == true || navigationRouter.body?.isNotEmpty == true; } static String get emailEMLPreviewerRoutePath => _createEmailEMLPreviewerServicePath('$baseOriginUrl${AppRoutes.emailEMLPreviewer}').path; static String generateMailtoLink(String mailAddress) { return '$baseOriginUrl/$mailtoPrefix/?uri=$mailtoPrefix:$mailAddress'; } static String? getRootDomain({String? hostname}) { final host = hostname ?? html.window.location.hostname; if (host == null || host.isEmpty) { return null; } final parts = host.split('.'); if (parts.length >= 2) { return '${parts[parts.length - 2]}.${parts.last}'; } return host; } }