internal void ProcessDeepLink(string token, DeepLinkRoute route, List <string> args)
        {
            switch (route)
            {
            case DeepLinkRoute.openprojectrequest:
                // /ServerId is first arg, ProjectId is the third
                if (args.Count >= 4)
                {
                    Debug.Log($"ProcessDeepLink, detected openprojectrequest Route request to open '{args[3]}' referenced project.");
                    // TODO : use sourceId param to filter visible sources
                    var sourceId = args.Count >= 6 ? args[5] : string.Empty;
                    // last args following projectId or sourceId is the intended viewerId target, it can also be omitted.
                    var viewerId = string.Empty;
                    switch (args.Count)
                    {
                    case 5:
                        viewerId = args[4];
                        break;

                    case 7:
                        viewerId = args[6];
                        break;
                    }
                    // Automation request can have token attached
                    if (!string.IsNullOrEmpty(token))
                    {
                        ResetToken(token);
                    }
                    openInViewerDetected?.Invoke(new OpenInViewerInfo(args[1], args[3], sourceId, viewerId));
                }
                break;

            case DeepLinkRoute.implicitcallbacklogin:
                ProcessToken(token);
                break;

            case DeepLinkRoute.opensharelink:
                // Second argument is the UID reference to be used to query cloud for ProjectId/ServerId
                if (args.Count >= 2)
                {
                    // Automation request can have token attached
                    if (!string.IsNullOrEmpty(token))
                    {
                        ResetToken(token);
                    }
                    Debug.Log($"ProcessDeepLink, detected opensharelink Route request to open '{args[1]}' referenced project.");
                    linkSharingDetected?.Invoke(args[1]);
                }
                break;
            }
        }
        internal static bool TryParseDeepLink(string deepLinkUrlString, out string token, out DeepLinkRoute route, out List <string> args)
        {
            token = string.Empty;
            route = DeepLinkRoute.none;
            args  = new List <string>();
            if (Uri.TryCreate(deepLinkUrlString, UriKind.Absolute, out var uriResult))
            {
                if (uriResult.Query.Length > 0)
                {
                    token = uriResult.Query.Substring(AuthConfiguration.JwtParamName.Length);
                }

                var knownRoute = Enum.TryParse(uriResult.Host, out DeepLinkRoute deepLink);
                // Make special case of implicit/callback/login as implicit is a keyword in C#
                if (!knownRoute)
                {
                    if (uriResult.Host.Equals("implicit") && uriResult.AbsolutePath.StartsWith("/callback/login"))
                    {
                        knownRoute = true;
                        deepLink   = DeepLinkRoute.implicitcallbacklogin;
                    }
                    else if (s_AllowedDomainsRegex.IsMatch(uriResult.Host))
                    {
                        knownRoute = true;
                        deepLink   = DeepLinkRoute.opensharelink;
                    }
                }

                if (knownRoute)
                {
                    route = deepLink;
                    args  = uriResult.AbsolutePath.Split('/').ToList();
                    args.RemoveAt(0);
                }
                return(knownRoute && uriResult.Scheme.Equals(AuthConfiguration.UriScheme, StringComparison.OrdinalIgnoreCase));
            }
            else
            {
                return(false);
            }
        }