text: 'use strict';
  
  Object.defineProperty(exports, "__esModule", {
    value: true
  });
  exports.generateAndStoreTransitKey = generateAndStoreTransitKey;
  exports.getTransitKey = getTransitKey;
  exports.isUserSignedIn = isUserSignedIn;
  exports.redirectToSignInWithAuthRequest = redirectToSignInWithAuthRequest;
  exports.redirectToSignIn = redirectToSignIn;
  exports.getAuthResponseToken = getAuthResponseToken;
  exports.isSignInPending = isSignInPending;
  exports.handlePendingSignIn = handlePendingSignIn;
  exports.loadUserData = loadUserData;
  exports.signUserOut = signUserOut;
  
  var _queryString = require('query-string');
  
  var _queryString2 = _interopRequireDefault(_queryString);
  
  var _jsontokens = require('jsontokens');
  
  var _customProtocolDetectionBlockstack = require('custom-protocol-detection-blockstack');
  
  var _customProtocolDetectionBlockstack2 = _interopRequireDefault(_customProtocolDetectionBlockstack);
  
  var _index = require('./index');
  
  var _utils = require('../utils');
  
  var _index2 = require('../index');
  
  var _errors = require('../errors');
  
  var _authMessages = require('./authMessages');
  
  var _authConstants = require('./authConstants');
  
  var _storage = require('../storage');
  
  var _profiles = require('../profiles');
  
  var _logger = require('../logger');
  
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
  
  var DEFAULT_PROFILE = {
    '@type': 'Person',
    '@context': 'http://schema.org'
  
    /**
     * Generates a ECDSA keypair and stores the hex value of the private key in
     * local storage.
     * @return {String} the hex encoded private key
     * @private
     */
  };function generateAndStoreTransitKey() {
    var transitKey = (0, _index2.makeECPrivateKey)();
    localStorage.setItem(_authConstants.BLOCKSTACK_APP_PRIVATE_KEY_LABEL, transitKey);
    return transitKey;
  }
  
  /**
   * Fetches the hex value of the transit private key from local storage.
   * @return {String} the hex encoded private key
   * @private
   */
  function getTransitKey() {
    var transitKey = localStorage.getItem(_authConstants.BLOCKSTACK_APP_PRIVATE_KEY_LABEL);
    return transitKey;
  }
  
  /**
   * Check if a user is currently signed in.
   * @return {Boolean} `true` if the user is signed in, `false` if not.
   */
  function isUserSignedIn() {
    return !!window.localStorage.getItem(_authConstants.BLOCKSTACK_STORAGE_LABEL);
  }
  
  /**
   * Redirects the user to the Blockstack browser to approve the sign in request
   * given.
   *
   * The user is redirected to the `blockstackIDHost` if the `blockstack:`
   * protocol handler is not detected. Please note that the protocol handler detection
   * does not work on all browsers.
   * @param  {String} authRequest - the authentication request generated by `makeAuthRequest`
   * @param  {String} blockstackIDHost - the URL to redirect the user to if the blockstack
   *                                     protocol handler is not detected
   * @return {void}
   */
  function redirectToSignInWithAuthRequest() {
    var authRequest = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : (0, _index.makeAuthRequest)();
    var blockstackIDHost = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : _authConstants.DEFAULT_BLOCKSTACK_HOST;
  
    var protocolURI = _utils.BLOCKSTACK_HANDLER + ':' + authRequest;
    var httpsURI = blockstackIDHost + '?authRequest=' + authRequest;
  
    // If they're on a mobile OS, always redirect them to HTTPS site
    if (/Android|webOS|iPhone|iPad|iPod|Opera Mini/i.test(navigator.userAgent)) {
      _logger.Logger.info('detected mobile OS, sending to https');
      window.location = httpsURI;
      return;
    }
  
    function successCallback() {
      _logger.Logger.info('protocol handler detected');
      // protocolCheck should open the link for us
    }
  
    function failCallback() {
      _logger.Logger.warn('protocol handler not detected');
      window.location = httpsURI;
    }
  
    function unsupportedBrowserCallback() {
      // Safari is unsupported by protocolCheck
      _logger.Logger.warn('can not detect custom protocols on this browser');
      window.location = protocolURI;
    }
  
    (0, _customProtocolDetectionBlockstack2.default)(protocolURI, failCallback, successCallback, unsupportedBrowserCallback);
  }
  
  /**
   * Generates an authentication request and redirects the user to the Blockstack
   * browser to approve the sign in request.
   *
   * Please note that this requires that the web browser properly handles the
   * `blockstack:` URL protocol handler.
   *
   * Most applications should use this
   * method for sign in unless they require more fine grained control over how the
   * authentication request is generated. If your app falls into this category,
   * use `generateAndStoreTransitKey`, `makeAuthRequest`,
   * and `redirectToSignInWithAuthRequest` to build your own sign in process.
   *
   * @param {String} [redirectURI=`${window.location.origin}/`]
   * The location to which the identity provider will redirect the user after
   * the user approves sign in.
   * @param  {String} [manifestURI=`${window.location.origin}/manifest.json`]
   * Location of the manifest file.
   * @param  {Array} [scopes=DEFAULT_SCOPE] Defaults to requesting write access to
   * this app's data store.
   * An array of strings indicating which permissions this app is requesting.
   * @return {void}
   */
  function redirectToSignIn() {
    var redirectURI = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : window.location.origin + '/';
    var manifestURI = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : window.location.origin + '/manifest.json';
    var scopes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : _authConstants.DEFAULT_SCOPE;
  
    var authRequest = (0, _index.makeAuthRequest)(generateAndStoreTransitKey(), redirectURI, manifestURI, scopes);
    redirectToSignInWithAuthRequest(authRequest);
  }
  
  /**
   * Retrieve the authentication token from the URL query
   * @return {String} the authentication token if it exists otherwise `null`
   */
  function getAuthResponseToken() {
    var queryDict = _queryString2.default.parse(location.search);
    return queryDict.authResponse ? queryDict.authResponse : '';
  }
  
  /**
   * Check if there is a authentication request that hasn't been handled.
   * @return {Boolean} `true` if there is a pending sign in, otherwise `false`
   */
  function isSignInPending() {
    return !!getAuthResponseToken();
  }
  
  /**
   * Try to process any pending sign in request by returning a `Promise` that resolves
   * to the user data object if the sign in succeeds.
   *
   * @param {String} nameLookupURL - the endpoint against which to verify public
   * keys match claimed username
   * @param {String} authResponseToken - the signed authentication response token
   * @param {String} transitKey - the transit private key that corresponds to the transit public key
   * that was provided in the authentication request
   * @return {Promise} that resolves to the user data object if successful and rejects
   * if handling the sign in request fails or there was no pending sign in request.
   */
  function handlePendingSignIn() {
    var nameLookupURL = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'https://core.blockstack.org/v1/names/';
    var authResponseToken = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : getAuthResponseToken();
    var transitKey = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : getTransitKey();
  
    return (0, _index.verifyAuthResponse)(authResponseToken, nameLookupURL).then(function (isValid) {
      if (!isValid) {
        throw new _errors.LoginFailedError('Invalid authentication response.');
      }
      var tokenPayload = (0, _jsontokens.decodeToken)(authResponseToken).payload;
      // TODO: real version handling
      var appPrivateKey = tokenPayload.private_key;
      var coreSessionToken = tokenPayload.core_token;
      if ((0, _utils.isLaterVersion)(tokenPayload.version, '1.1.0')) {
        if (transitKey !== undefined && transitKey != null) {
          if (tokenPayload.private_key !== undefined && tokenPayload.private_key !== null) {
            try {
              appPrivateKey = (0, _authMessages.decryptPrivateKey)(transitKey, tokenPayload.private_key);
            } catch (e) {
              _logger.Logger.warn('Failed decryption of appPrivateKey, will try to use as given');
              try {
                (0, _utils.hexStringToECPair)(tokenPayload.private_key);
              } catch (ecPairError) {
                throw new _errors.LoginFailedError('Failed decrypting appPrivateKey. Usually means' + ' that the transit key has changed during login.');
              }
            }
          }
          if (coreSessionToken !== undefined && coreSessionToken !== null) {
            try {
              coreSessionToken = (0, _authMessages.decryptPrivateKey)(transitKey, coreSessionToken);
            } catch (e) {
              _logger.Logger.info('Failed decryption of coreSessionToken, will try to use as given');
            }
          }
        } else {
          throw new _errors.LoginFailedError('Authenticating with protocol > 1.1.0 requires transit' + ' key, and none found.');
        }
      }
      var hubUrl = _authConstants.BLOCKSTACK_DEFAULT_GAIA_HUB_URL;
      if ((0, _utils.isLaterVersion)(tokenPayload.version, '1.2.0') && tokenPayload.hubUrl !== null && tokenPayload.hubUrl !== undefined) {
        hubUrl = tokenPayload.hubUrl;
      }
  
      var userData = {
        username: tokenPayload.username,
        profile: tokenPayload.profile,
        decentralizedID: tokenPayload.iss,
        identityAddress: (0, _index2.getAddressFromDID)(tokenPayload.iss),
        appPrivateKey: appPrivateKey,
        coreSessionToken: coreSessionToken,
        authResponseToken: authResponseToken,
        hubUrl: hubUrl
      };
      var profileURL = tokenPayload.profile_url;
      if ((userData.profile === null || userData.profile === undefined) && profileURL !== undefined && profileURL !== null) {
        return fetch(profileURL).then(function (response) {
          if (!response.ok) {
            // return blank profile if we fail to fetch
            userData.profile = Object.assign({}, DEFAULT_PROFILE);
            window.localStorage.setItem(_authConstants.BLOCKSTACK_STORAGE_LABEL, JSON.stringify(userData));
            return userData;
          } else {
            return response.text().then(function (responseText) {
              return JSON.parse(responseText);
            }).then(function (wrappedProfile) {
              return (0, _profiles.extractProfile)(wrappedProfile[0].token);
            }).then(function (profile) {
              userData.profile = profile;
              window.localStorage.setItem(_authConstants.BLOCKSTACK_STORAGE_LABEL, JSON.stringify(userData));
              return userData;
            });
          }
        });
      } else {
        userData.profile = tokenPayload.profile;
        window.localStorage.setItem(_authConstants.BLOCKSTACK_STORAGE_LABEL, JSON.stringify(userData));
        return userData;
      }
    });
  }
  
  /**
   * Retrieves the user data object. The user's profile is stored in the key `profile`.
   * @return {Object} User data object.
   */
  function loadUserData() {
    return JSON.parse(window.localStorage.getItem(_authConstants.BLOCKSTACK_STORAGE_LABEL));
  }
  
  /**
   * Sign the user out and optionally redirect to given location.
   * @param  {String} [redirectURL=null] Location to redirect user to after sign out.
   * @return {void}
   */
  function signUserOut() {
    var redirectURL = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : null;
  
    window.localStorage.removeItem(_authConstants.BLOCKSTACK_STORAGE_LABEL);
    window.localStorage.removeItem(_storage.BLOCKSTACK_GAIA_HUB_LABEL);
  
    if (redirectURL !== null) {
      window.location = redirectURL;
    }
  }