private static FileInfo GetAvailableTarballs(out FileInfo[] packages)
        {
            var      installerScript = MonoScript.FromScriptableObject(OpenVRPackageInstaller.CreateInstance <OpenVRPackageInstaller>());
            var      scriptPath      = AssetDatabase.GetAssetPath(installerScript);
            FileInfo thisScript      = new FileInfo(scriptPath);

            packages = thisScript.Directory.GetFiles("*.tgz");

            if (packages.Length > 0)
            {
                if (packages.Length > 1)
                {
                    var descending = packages.OrderByDescending(file => file.Name);
                    var latest     = descending.First();
                    packages = descending.Where(file => file != latest).ToArray();
                    return(latest);
                }

                var onlyPackage = packages[0];
                packages = new FileInfo[0];
                return(onlyPackage);
            }
            else
            {
                return(null);
            }
        }
        /// <summary>
        /// State Machine
        /// Idle: Start from last known state. If none is known, ask user if they want to install, if yes goto remove scoped registry step
        /// WaitingOnExistingCheck:
        /// RemoveScopedRegistry: Remove the scoped registry entry if it exists
        /// WaitingForAdd: if the add request has been nulled or completed successfully, request a list of packages for confirmation
        /// WaitingForAddConfirmation: enumerate the packages and verify the add succeeded. If it failed, try again.
        ///                                 If it succeeded request removal of this script
        /// RemoveSelf: delete the key that we've been using to maintain state. Delete this script and the containing folder if it's empty.
        /// </summary>
        private static void Update()
        {
            switch (updateState)
            {
            case UpdateStates.Idle:
                if (EditorPrefs.HasKey(updaterKey))
                {
                    _updateState = (UpdateStates)EditorPrefs.GetInt(updaterKey);
                    packageTime.Start();
                }
                else
                {
                    RequestExisting();
                }
                break;

            case UpdateStates.WaitingOnExistingCheck:
                if (listRequest == null)
                {
                    //the list request got nulled for some reason. Request it again.
                    RequestExisting();
                }
                else if (listRequest != null && listRequest.IsCompleted)
                {
                    if (listRequest.Error != null || listRequest.Status == UnityEditor.PackageManager.StatusCode.Failure)
                    {
                        DisplayErrorAndStop("Error while checking for an existing OpenVR package.", listRequest);
                    }
                    else
                    {
                        if (listRequest.Result.Any(package => package.name == valveOpenVRPackageString))
                        {
                            var existingPackage = listRequest.Result.FirstOrDefault(package => package.name == valveOpenVRPackageString);

                            string latestTarball = GetLatestTarballVersion();

                            if (latestTarball != null && latestTarball.CompareTo(existingPackage.version) == 1)
                            {
                                //we have a tarball higher than the currently installed version
                                string upgradeString = string.Format("This SteamVR Unity Plugin has a newer version of the Unity XR OpenVR package than you have installed. Would you like to upgrade?\n\nCurrent: {0}\nUpgrade: {1} (recommended)", existingPackage.version, latestTarball);
                                bool   upgrade       = UnityEditor.EditorUtility.DisplayDialog("OpenVR XR Updater", upgradeString, "Upgrade", "Cancel");
                                if (upgrade)
                                {
                                    RemoveScopedRegistry();
                                }
                                else
                                {
                                    bool delete = UnityEditor.EditorUtility.DisplayDialog("OpenVR XR Updater", "Would you like to remove this updater script so we don't ask again?", "Remove updater", "Keep");
                                    if (delete)
                                    {
                                        Stop();
                                        return;
                                    }
                                    else
                                    {
                                        GentleStop();
                                        return;
                                    }
                                }
                            }
                        }
                        else
                        {
                                #if UNITY_2020_1_OR_NEWER
                            RemoveScopedRegistry();     //just install if we're on 2020 and they don't have the package
                            return;
                                #else
                            //they don't have the package yet. Ask if they want to install (only for 2019)
                            bool blankInstall = UnityEditor.EditorUtility.DisplayDialog("OpenVR XR Installer", "The SteamVR Unity Plugin can be used with the legacy Unity VR API (Unity 5.4 - 2019) or with the Unity XR API (2019+). Would you like to install OpenVR for Unity XR?", "Install", "Cancel");
                            if (blankInstall)
                            {
                                RemoveScopedRegistry();
                            }
                            else
                            {
                                bool delete = UnityEditor.EditorUtility.DisplayDialog("OpenVR XR Installer", "Would you like to remove this installer script so we don't ask again?", "Remove installer", "Keep");
                                if (delete)
                                {
                                    Stop();
                                    return;
                                }
                                else
                                {
                                    GentleStop();
                                    return;
                                }
                            }
                                #endif
                        }
                    }
                }
                break;

            case UpdateStates.WaitingForAdd:
                if (addRequest == null)
                {
                    //the add request got nulled for some reason. Request an add confirmation
                    RequestAddConfirmation();
                }
                else if (addRequest != null && addRequest.IsCompleted)
                {
                    if (addRequest.Error != null || addRequest.Status == UnityEditor.PackageManager.StatusCode.Failure)
                    {
                        DisplayErrorAndStop("Error adding new version of OpenVR package.", addRequest);
                    }
                    else
                    {
                        //verify that the package has been added (then stop)
                        RequestAddConfirmation();
                    }
                }
                else
                {
                    if (packageTime.Elapsed.TotalSeconds > estimatedTimeToInstall)
                    {
                        DisplayErrorAndStop("Error while trying to add package.", addRequest);
                    }
                    else
                    {
                        DisplayProgressBar();
                    }
                }
                break;

            case UpdateStates.WaitingForAddConfirmation:
                if (listRequest == null)
                {
                    //the list request got nulled for some reason. Request it again.
                    RequestAddConfirmation();
                }
                else if (listRequest != null && listRequest.IsCompleted)
                {
                    if (listRequest.Error != null || listRequest.Status == UnityEditor.PackageManager.StatusCode.Failure)
                    {
                        DisplayErrorAndStop("Error while confirming the OpenVR package has been added.", listRequest);
                    }
                    else
                    {
                        if (listRequest.Result.Any(package => package.name == valveOpenVRPackageString))
                        {
                            updateState = UpdateStates.RemoveSelf;
                            UnityEditor.EditorUtility.DisplayDialog("OpenVR Unity XR Installer", "OpenVR Unity XR successfully installed.\n\nA restart of the Unity Editor may be necessary.", "Ok");
                        }
                        else
                        {
                            //try to add again if it's not there and we don't know why
                            RequestAdd();
                        }
                    }
                }
                else
                {
                    if (runningSeconds > estimatedTimeToInstall)
                    {
                        DisplayErrorAndStop("Error while confirming the OpenVR package has been added.", listRequest);
                    }
                    else
                    {
                        DisplayProgressBar();
                    }
                }
                break;

            case UpdateStates.RemoveSelf:
                EditorPrefs.DeleteKey(updaterKey);
                EditorUtility.ClearProgressBar();
                EditorApplication.update -= Update;

#if VALVE_SKIP_DELETE
                Debug.Log("[DEBUG] skipping script deletion. Complete.");
                return;
#endif

                var      script               = MonoScript.FromScriptableObject(OpenVRPackageInstaller.CreateInstance <OpenVRPackageInstaller>());
                var      path                 = AssetDatabase.GetAssetPath(script);
                FileInfo updaterScript        = new FileInfo(path); updaterScript.IsReadOnly = false;
                FileInfo updaterScriptMeta    = new FileInfo(path + ".meta");
                FileInfo simpleJSONScript     = new FileInfo(Path.Combine(updaterScript.Directory.FullName, "OpenVRSimpleJSON.cs"));
                FileInfo simpleJSONScriptMeta = new FileInfo(Path.Combine(updaterScript.Directory.FullName, "OpenVRSimpleJSON.cs.meta"));

                updaterScript.IsReadOnly        = false;
                updaterScriptMeta.IsReadOnly    = false;
                simpleJSONScript.IsReadOnly     = false;
                simpleJSONScriptMeta.IsReadOnly = false;

                updaterScriptMeta.Delete();
                if (updaterScriptMeta.Exists)
                {
                    DisplayErrorAndStop("Error while removing package installer script. Please delete manually.", listRequest);
                    return;
                }

                simpleJSONScript.Delete();
                simpleJSONScriptMeta.Delete();
                updaterScript.Delete();

                AssetDatabase.Refresh();
                break;
            }
        }