text: import { NativeEventEmitter } from "react-native";
  import RestartManager from "./RestartManager";
  import log from "./logging";
  
  // This function is used to augment remote and local
  // package objects with additional functionality/properties
  // beyond what is included in the metadata sent by the server.
  module.exports = (NativeGreatPush) => {
    const remote = (reportStatusDownload) => {
      return {
        async download(downloadProgressCallback) {
          if (!this.downloadUrl) {
            throw new Error("Cannot download an update without a download url");
          }
  
          let downloadProgressSubscription;
          if (downloadProgressCallback) {
            const greatPushEventEmitter = new NativeEventEmitter(NativeGreatPush);
            // Use event subscription to obtain download progress.
            downloadProgressSubscription = greatPushEventEmitter.addListener(
              "GreatPushDownloadProgress",
              downloadProgressCallback
            );
          }
  
          // Use the downloaded package info. Native code will save the package info
          // so that the client knows what the current package version is.
          try {
            const updatePackageCopy = Object.assign({}, this);
            Object.keys(updatePackageCopy).forEach((key) => (typeof updatePackageCopy[key] === 'function') && delete updatePackageCopy[key]);
  
            const downloadedPackage = await NativeGreatPush.downloadUpdate(updatePackageCopy, !!downloadProgressCallback);
  
            if (reportStatusDownload) {
              reportStatusDownload(this)
              .catch((err) => {
                log(`Report download status failed: ${err}`);
              });
            }
  
            return { ...downloadedPackage, ...local };
          } finally {
            downloadProgressSubscription && downloadProgressSubscription.remove();
          }
        },
  
        isPending: false // A remote package could never be in a pending state
      };
    };
  
    const local = {
      async install(installMode = NativeGreatPush.greatPushInstallModeOnNextRestart, minimumBackgroundDuration = 0, updateInstalledCallback) {
        const localPackage = this;
        const localPackageCopy = Object.assign({}, localPackage); // In dev mode, React Native deep freezes any object queued over the bridge
        await NativeGreatPush.installUpdate(localPackageCopy, installMode, minimumBackgroundDuration);
        updateInstalledCallback && updateInstalledCallback();
        if (installMode == NativeGreatPush.greatPushInstallModeImmediate) {
          RestartManager.restartApp(false);
        } else {
          RestartManager.clearPendingRestart();
          localPackage.isPending = true; // Mark the package as pending since it hasn't been applied yet
        }
      },
  
      isPending: false // A local package wouldn't be pending until it was installed
    };
  
    return { local, remote };
  };