text: const fetch = require('node-fetch');
  const Package = require('../package.json');
  
  const Account = require('./Account');
  const Match = require('./Match').Match;
  const StoreItem = require('./StoreItem');
  const Challenges = require('./Challenges');
  
  /**
   * The client for interacting with the Fortnite Tracker API
   * @class Client
   * @param {string} key Fortnite Tracker API token
   */
  class Client {
      constructor(key) {
  
          if (!key) {
              throw new Error('No API key passed.');
          }
  
          this.key = key;
  
          this.headers = {
              'User-Agent': `fortnite.js v${Package.version} (${Package.homepage})`,
              'TRN-Api-Key': this.key
          };
  
          this.rateLimit = {
              limit: 30,
              remaining: 30
          };
  
      }
  
      /**
       * Makes the request to the API
       * @private
       * @param {string} link URL endpoint of API
       * @returns {Promise<Object>}
       * @memberof Client
       */
      _request(link) {
          return fetch(link, { headers: this.headers })
              .then(r => {
                  this.rateLimit = {
                      limit: Number(r.headers.get('x-ratelimit-limit-minute')),
                      remaining: Number(r.headers.get('x-ratelimit-remaining-minute'))
                  };
  
                  if (!r.ok) return Promise.reject(r.statusText);
  
                  return r.json();
              })
              .catch(e => Promise.reject(`HTTP ${e}`));
      }
  
      /**
       * Get user info
       * @param {string} username username of the user to search for
       * @param {string=} [platform='pc'] platform to search for user in (pc, xbl, or psn)
       * @param {boolean=} [raw=false] whether to return raw response from API
       * @returns {(Promise<Account>|Promise<Object>)}
       * @memberof Client
       */
      get(username, platform = 'pc', raw = false) {
          return this._request(`https://api.fortnitetracker.com/v1/profile/${platform}/${encodeURI(username)}`)
              .then(r => r.error ? Promise.reject(r) : r)
              .then(r => raw ? r : new Account(r))
              .catch(e => Promise.reject(e));
      }
  
      /**
       * Get user's matches
       * @param {string} accountId user's account ID found in user info
       * @param {boolean=} [raw=false] whether to return raw response from API
       * @returns {(Promise<Array<Match>>|Promise<Array<Object>>)}
       * @memberof Client
       */
      getMatches(accountId, raw = false) {
          return this._request(`https://api.fortnitetracker.com/v1/profile/account/${accountId}/matches`)
              .then(r => r.error ? Promise.reject(r.error) : r)
              .then(r => raw ? r : r.map(m => new Match(m)))
              .catch(e => Promise.reject(e));
      }
  
      /**
       * Get current store items
       * @param {boolean=} [raw=false] whether to return raw response from API
       * @returns {Promise<Array<StoreItem>>|Promise<Array<Object>>}
       * @memberof Client
       */
      getStore(raw = false) {
          return this._request('https://api.fortnitetracker.com/v1/store')
              .then(r => r.error ? Promise.reject(r.error) : r)
              .then(r => raw ? r : r.map(item => new StoreItem(item)))
              .catch(e => Promise.reject(e));
      }
  
      /**
       * Get currently weekly challenges
       * @param {boolean=} [raw=false] whether to return raw response from API
       * @returns {(Promise<Challenges>|Promise<Object>)}
       * @memberof Client
       */
      getChallenges(raw = false) {
          return this._request('https://api.fortnitetracker.com/v1/challenges')
              .then(r => r.error ? Promise.reject(r.error) : r)
              .then(r => raw ? r : new Challenges(r))
              .catch(e => Promise.reject(e));
      }
  }
  
  module.exports = Client;