static bool WaitForUpdate(ref bool isDone, int timeout, bool errorOnTimeout = true)
        {
            s_Stopwatch.Reset();
            s_Stopwatch.Start();

            do
            {
                AssetStoreClient.Update();
                Thread.Sleep(10);
                if (AssetStoreClient.LoginError())
                {
                    Debug.LogError("Found Login error: " + AssetStoreClient.LoginErrorMessage);
                    break;
                }

                if (!isDone && s_Stopwatch.Elapsed.TotalSeconds > timeout)
                {
                    if (errorOnTimeout)
                    {
                        throw new TimeoutException("Asset Store batch mode operation timed out.");
                    }

                    break;
                }
            } while (!isDone);

            return(isDone);
        }
        // -----------------------------------------------
        // Helper functions
        // -----------------------------------------------

        static void Finish()
        {
            AssetStoreClient.Logout();
            s_LoginDone          = false;
            s_GetMetadataDone    = false;
            s_AssetsUploadedDone = false;
        }
        public static void UploadAssets(Package package, string localRootGuid, string localRootPath, string projectPath, string draftAssetsPath, DoneCallback callback, AssetStoreClient.ProgressCallback progressCallback)
        {
            Type doneCallbackType, clientProgressCallbackType;
            var  doneCallback           = CreateCallbackDelegate("DoneCallback", callback, out doneCallbackType);
            var  clientProgressCallback = AssetStoreClient.CreateCallbackDelegate("ProgressCallback", progressCallback, out clientProgressCallbackType);

            s_Instance.GetRuntimeType().Invoke("UploadAssets", package.GetRuntimeObject().Param(), localRootGuid.Param(), localRootPath.Param(), projectPath.Param(), draftAssetsPath.Param(), new Parameter(doneCallback, doneCallbackType), new Parameter(clientProgressCallback, clientProgressCallbackType));
        }
        // -----------------------------------------------
        // Helper functions
        // -----------------------------------------------

        static void Finish()
        {
            Debug.Log("Logout client");
            AssetStoreClient.Logout();
            s_LoginDone          = false;
            s_GetMetadataDone    = false;
            s_AssetsUploadedDone = false;
            //AssetStoreClient.Update();
            Debug.Log("Logout finished");
        }
        private static void StartLogin()
        {
            if (AssetStoreClient.LoggedIn() == false)
            {
                Debug.Log("[Asset Store Batch Mode] Logging into the Asset Store...");

                s_Stopwatch.Reset();
                s_Stopwatch.Start();
                AssetStoreClient.LoginWithCredentials(s_Username, s_Password, false, OnLogin);
                CurrentState = State.WaitingForLogin;
            }
            else
            {
                Debug.Log("[Asset Store Batch Mode] Already logged in.");
                CurrentState = State.GetMetadata;
            }
        }
        static bool WaitForUpdate(ref bool isDone, int timeout)
        {
            s_Stopwatch.Reset();
            s_Stopwatch.Start();

            do
            {
                AssetStoreClient.Update();
                Thread.Sleep(10);
                if (!isDone && s_Stopwatch.Elapsed.TotalSeconds > timeout)
                {
                    throw new TimeoutException("Asset Store batch mode operation timed out.");
                }
            } while (!isDone);

            return(isDone);
        }
        private static void Update()
        {
            AssetStoreClient.Update();
            switch (CurrentState)
            {
            case State.Login:
                StartLogin();
                return;

            case State.WaitingForLogin:
                WaitingForLogin();
                return;

            case State.GetMetadata:
                StartGetMetadata();
                return;

            case State.WaitingForMetadata:
                WaitForMetadata();
                return;

            case State.Upload:
                UploadPackage();
                break;

            case State.WaitingForUpload:
                WaitForUpload();
                break;

            case State.Error:
            case State.Finished:
                Debug.Log("FINISHED");
                Finish();
                EditorApplication.update -= Update;
                OnFinished();
                return;

            default:
                throw new ArgumentOutOfRangeException();
            }
        }
        private static void WaitingForLogin()
        {
            if (s_LoginDone == false)
            {
                if (AssetStoreClient.LoginError())
                {
                    Debug.LogError("Found Login error: " + AssetStoreClient.LoginErrorMessage);
                    CurrentState = State.Error;
                    return;
                }

                if (s_Stopwatch.Elapsed.TotalSeconds > s_LoginTimeout)
                {
                    Debug.LogError("Asset Store batch mode operation timed out.");
                    CurrentState = State.Error;
                }
            }
            else
            {
                CurrentState = State.GetMetadata;
            }
        }
 static AssetStoreClient()
 {
     s_Instance = new AssetStoreClient();
     s_Instance.GetRuntimeType().Assembly.GetType("AssetStoreManager").SetFieldValue("sDbg", true);
 }
        /// <summary>
        /// Upload a package, using the specified options.
        /// </summary>
        /// <param name="username">The username credentials to use for package uploading.</param>
        /// <param name="password">The password credentials to use for package uploading.</param>
        /// <param name="packageName">The package name. The package must be set to draft status in the Publisher Administration.</param>
        /// <param name="rootPath">The root path of the package (relative to Application.dataPath). If null, use the project Assets folder.</param>
        /// <param name="mainAssets">An array of the main assets for the package (relative to Application.dataPath). If null, do not upload or change any main assets.</param>
        /// <param name="loginTimeout">The maximum amount of time to wait (in seconds) when logging in. Defaults to 90 seconds. Must be within 2 and 36000 seconds. Login is attempted twice.</param>
        /// <param name="metadataTimeout">The maximum amount of time to wait (in seconds) when getting metadata. Defaults to 600 seconds. Must be within 2 and 36000 seconds.</param>
        /// <param name="uploadTimeout">The maximum amount of time to wait (in seconds) when uploading. Defaults to 36000 seconds. Must be within 2 and 36000 seconds.</param>
        /// <param name="guidListPostprocessCallback = null">Callback that takes the array of asset GUIDs and returns a modified one. Useful for filtering out unwanted assets.</param>
        public static void UploadAssetStorePackage(string username, string password, string packageName, string rootPath = null, string[] mainAssets = null, int loginTimeout = 90, int metadataTimeout = 600, int uploadTimeout = 36000, bool skipProjectSettings = false, GuidListPostprocessCallback guidListPostprocessCallback = null)
        {
            if (string.IsNullOrEmpty(username))
            {
                throw new ArgumentNullException("username");
            }

            if (string.IsNullOrEmpty(password))
            {
                throw new ArgumentNullException("password");
            }

            if (string.IsNullOrEmpty(packageName))
            {
                throw new ArgumentNullException("packageName");
            }

            s_Username                    = username;
            s_Password                    = password;
            s_PackageName                 = packageName;
            s_RootPath                    = rootPath;
            s_MainAssets                  = mainAssets;
            s_LoginTimeout                = Mathf.Clamp(loginTimeout, 2, 36000);
            s_MetadataTimeout             = Mathf.Clamp(metadataTimeout, 2, 36000);
            s_UploadTimeout               = Mathf.Clamp(uploadTimeout, 2, 36000);
            s_SkipProjectSettings         = skipProjectSettings;
            s_GuidListPostprocessCallback = guidListPostprocessCallback;

            Finish();

#if !UNITY_5_5_OR_NEWER
            if (Application.webSecurityEnabled)
            {
                Debug.Log("[Asset Store Batch Mode] Switching from Web Player platform...");

                EditorUserBuildSettings.SwitchActiveBuildTarget(EditorUserBuildSettings.selectedStandaloneTarget);
            }
#endif

            Debug.Log("[Asset Store Batch Mode] Logging into the Asset Store...");

            AssetStoreClient.LoginWithCredentials(s_Username, s_Password, false, OnLogin);

            if (!WaitForUpdate(ref s_LoginDone, s_LoginTimeout))
            {
                Finish();

                // Try again
                s_LoginDone = false;
                AssetStoreClient.LoginWithCredentials(s_Username, s_Password, false, OnLogin);

                if (!WaitForUpdate(ref s_LoginDone, s_LoginTimeout))
                {
                    Finish();
                    return;
                }
            }

            AssetStoreAPI.GetMetaData(s_PublisherAccount, s_PackageDataSource, OnGetMetadata);

            Debug.Log("[Asset Store Batch Mode] Getting package metadata...");

            if (!WaitForUpdate(ref s_GetMetadataDone, s_MetadataTimeout))
            {
                Finish();
                return;
            }

            var packages = s_PackageDataSource.GetAllPackages();
            var package  = packages.FirstOrDefault(p => p.Name == s_PackageName && p.Status == Package.PublishedStatus.Draft);

            if (package == null)
            {
                Debug.LogError("[Asset Store Batch Mode] Draft package: " + s_PackageName + " not found!");
                Finish();
                return;
            }

            // Validate root project folder
            var projectFolder = Path.Combine(Application.dataPath, s_RootPath ?? string.Empty);

            // Convert to unix path style
            projectFolder = projectFolder.Replace("\\", "/");

            if (!IsValidProjectFolder(projectFolder))
            {
                Debug.LogError("[Asset Store Batch Mode] Project folder is invalid");
                Finish();
                return;
            }

            // Set root asset path
            var localRootPath = SetRootPath(package, projectFolder);

            // TODO: Set main assets

            // Verify content
            var checkContent = CheckContent(package, localRootPath);
            if (!string.IsNullOrEmpty(checkContent))
            {
                Debug.LogError("[Asset Store Batch Mode] " + checkContent);
                Finish();
                return;
            }

            var draftAssetsPath = GetDraftAssetsPath(localRootPath);

            Export(package, localRootPath, draftAssetsPath);

            // Upload assets
            AssetStoreAPI.UploadAssets(
                package,
                AssetStorePackageController.GetLocalRootGUID(package),
                localRootPath,
                Application.dataPath,
                draftAssetsPath,
                OnAssetsUploaded, null);

            Debug.Log("[Asset Store Batch Mode] Uploading asset...");

            if (!WaitForUpdate(ref s_AssetsUploadedDone, s_UploadTimeout))
            {
                Finish();
                return;
            }

            // TODO: Upload main assets

            Debug.Log("[Asset Store Batch Mode] Asset successfully uploaded");

            Finish();
        }