/**
 * Copyright (c) Nicolas Gallagher.
 * Copyright (c) Facebook, Inc. and its affiliates.
 *
 * This source code is licensed under the MIT license found in the
 * LICENSE file in the root directory of this source tree.
 */
// @ts-ignore Cannot find module 'merge-options' or its corresponding type declarations
import mergeOptions from 'merge-options';
const merge = mergeOptions.bind({
  concatArrays: true,
  ignoreUndefined: true
});

function mergeLocalStorageItem(key, value) {
  const oldValue = window.localStorage.getItem(key);

  if (oldValue) {
    const oldObject = JSON.parse(oldValue);
    const newObject = JSON.parse(value);
    const nextValue = JSON.stringify(merge(oldObject, newObject));
    window.localStorage.setItem(key, nextValue);
  } else {
    window.localStorage.setItem(key, value);
  }
}

function createPromise(getValue, callback) {
  return new Promise((resolve, reject) => {
    try {
      const value = getValue();
      callback === null || callback === void 0 ? void 0 : callback(null, value);
      resolve(value);
    } catch (err) {
      callback === null || callback === void 0 ? void 0 : callback(err);
      reject(err);
    }
  });
}

function createPromiseAll(promises, callback, processResult) {
  return Promise.all(promises).then(result => {
    var _processResult;

    const value = (_processResult = processResult === null || processResult === void 0 ? void 0 : processResult(result)) !== null && _processResult !== void 0 ? _processResult : null;
    callback === null || callback === void 0 ? void 0 : callback(null, value);
    return Promise.resolve(value);
  }, errors => {
    callback === null || callback === void 0 ? void 0 : callback(errors);
    return Promise.reject(errors);
  });
}

const AsyncStorage = {
  /**
   * Fetches `key` value.
   */
  getItem: (key, callback) => {
    return createPromise(() => window.localStorage.getItem(key), callback);
  },

  /**
   * Sets `value` for `key`.
   */
  setItem: (key, value, callback) => {
    return createPromise(() => window.localStorage.setItem(key, value), callback);
  },

  /**
   * Removes a `key`
   */
  removeItem: (key, callback) => {
    return createPromise(() => window.localStorage.removeItem(key), callback);
  },

  /**
   * Merges existing value with input value, assuming they are stringified JSON.
   */
  mergeItem: (key, value, callback) => {
    return createPromise(() => mergeLocalStorageItem(key, value), callback);
  },

  /**
   * Erases *all* AsyncStorage for the domain.
   */
  clear: callback => {
    return createPromise(() => window.localStorage.clear(), callback);
  },

  /**
   * Gets *all* keys known to the app, for all callers, libraries, etc.
   */
  getAllKeys: callback => {
    return createPromise(() => {
      const numberOfKeys = window.localStorage.length;
      const keys = [];

      for (let i = 0; i < numberOfKeys; i += 1) {
        const key = window.localStorage.key(i) || '';
        keys.push(key);
      }

      return keys;
    }, callback);
  },

  /**
   * (stub) Flushes any pending requests using a single batch call to get the data.
   */
  flushGetRequests: () => undefined,

  /**
   * multiGet resolves to an array of key-value pair arrays that matches the
   * input format of multiSet.
   *
   *   multiGet(['k1', 'k2']) -> [['k1', 'val1'], ['k2', 'val2']]
   */
  multiGet: (keys, callback) => {
    const promises = keys.map(key => AsyncStorage.getItem(key));

    const processResult = result => result.map((value, i) => [keys[i], value]);

    return createPromiseAll(promises, callback, processResult);
  },

  /**
   * Takes an array of key-value array pairs.
   *   multiSet([['k1', 'val1'], ['k2', 'val2']])
   */
  multiSet: (keyValuePairs, callback) => {
    const promises = keyValuePairs.map(item => AsyncStorage.setItem(item[0], item[1]));
    return createPromiseAll(promises, callback);
  },

  /**
   * Delete all the keys in the `keys` array.
   */
  multiRemove: (keys, callback) => {
    const promises = keys.map(key => AsyncStorage.removeItem(key));
    return createPromiseAll(promises, callback);
  },

  /**
   * Takes an array of key-value array pairs and merges them with existing
   * values, assuming they are stringified JSON.
   *
   *   multiMerge([['k1', 'val1'], ['k2', 'val2']])
   */
  multiMerge: (keyValuePairs, callback) => {
    const promises = keyValuePairs.map(item => {
      var _AsyncStorage$mergeIt, _AsyncStorage$mergeIt2;

      return (_AsyncStorage$mergeIt = (_AsyncStorage$mergeIt2 = AsyncStorage.mergeItem) === null || _AsyncStorage$mergeIt2 === void 0 ? void 0 : _AsyncStorage$mergeIt2.call(AsyncStorage, item[0], item[1])) !== null && _AsyncStorage$mergeIt !== void 0 ? _AsyncStorage$mergeIt : Promise.reject('Not implemented');
    });
    return createPromiseAll(promises, callback);
  }
};
export default AsyncStorage;
//# sourceMappingURL=AsyncStorage.js.map