<commit_before>'use strict';

import _ from 'lodash';
import rest from './lib/rest-client';

var tap = function(func){
  return function(value){
    func.apply(null, arguments);
    return value;
  }
}

var cronofy = function(config){
  if(!this || this.constructor !== cronofy){
    throw new Error("Cronofy must be called as a constructor");
  }

  this.config = config;

  this.urls = {
    api: 'https://api' + (config.dataCenter ? '-' + config.dataCenter : '') + '.cronofy.com'
  };
}

cronofy.prototype._httpCall = function(method, path, options, callback, optionsToOmit){
  var settings = {
    method: method,
    path: this.urls.api + path,
    headers: {
      Authorization: 'Bearer ' + options.access_token,
      'Content-Type': 'application/json'
    },
    entity: _.omit(options, optionsToOmit || ['access_token'])
  };

  return new Promise(function(resolve, reject){
    rest(settings).then(function(result){
      if(callback){
        callback(null, result['entity']);
      } else {
        resolve(result['entity']);
      }
    }, function(err){
      var error = new Error(JSON.stringify(err.entity));
      if(err.status){
        error.statusCode = err.status.code;
      }

      if(callback){
        callback(error);
      } else {
        reject(error);
      }
    });
  });
}

cronofy.prototype._parseArguments = function(args, configDefaults){
  var parsed = {options: {}, callback: null};

  if(args.length == 2){
    parsed.options = args[0];
    parsed.callback = args[1];
  } else {
    switch(typeof args[0]){
      case "object":
        parsed.options = args[0];
        break;
      case "function":
        parsed.callback = args[0];
        break;
    }
  }

  for(var i = 0; i < configDefaults.length; i++){
    var key = configDefaults[i];

    parsed.options[key] = parsed.options[key] || this.config[key];
  }

  return parsed;
}

cronofy.prototype._httpGet = function(path, options, callback, optionsToOmit){
  return this._httpCall('GET', path, options, callback, optionsToOmit);
}

cronofy.prototype._httpPost = function(path, options, callback, optionsToOmit){
  return this._httpCall('POST', path, options, callback, optionsToOmit);
}

cronofy.prototype._httpDelete = function(path, options, callback, optionsToOmit){
  return this._httpCall('DELETE', path, options, callback, optionsToOmit);
}

cronofy.prototype.accountInformation = function(){
  var details = this._parseArguments(arguments, ["access_token"]);

  return this._httpGet('/v1/account', details.options, details.callback);
}

cronofy.prototype.addToCalendar = function(){
  var details = this._parseArguments(arguments, ["client_id", "client_secret"]);

  return this._httpPost('/v1/add_to_calendar', details.options, details.callback);
}

cronofy.prototype.authorizeWithServiceAccount = function(){
  var details = this._parseArguments(arguments, ["access_token"]);

  return this._httpPost('/v1/service_account_authorizations', details.options, details.callback);
}

cronofy.prototype.availability = function(){
  var details = this._parseArguments(arguments, ["access_token"]);

  return this._httpPost('/v1/availability', details.options, details.callback);
}

cronofy.prototype.createEvent = function(){
  var details = this._parseArguments(arguments, ["access_token"]);

  return this._httpPost('/v1/calendars/' + details.options.calendar_id + '/events', details.options, details.callback, ['access_token', 'calendar_id']);
}

cronofy.prototype.createNotificationChannel = function(){
  var details = this._parseArguments(arguments, ["access_token"]);

  return this._httpPost('/v1/channels', details.options, details.callback);
}

cronofy.prototype.deleteEvent = function(){
  var details = this._parseArguments(arguments, ["access_token"]);

  return this._httpDelete('/v1/calendars/' + details.options.calendar_id + '/events', details.options, details.callback, ['access_token', 'calendar_id']);
}

cronofy.prototype.deleteExternalEvent = function(){
  var details = this._parseArguments(arguments, ["access_token"]);

  return this._httpDelete('/v1/calendars/' + details.options.calendar_id + '/events', details.options, details.callback, ['access_token', 'calendar_id']);
}

cronofy.prototype.deleteNotificationChannel = function(){
  var details = this._parseArguments(arguments, ["access_token"]);

  return this._httpDelete('/v1/channels/' + details.options.channel_id, details.options, details.callback, ['access_token', 'channel_id']);
}

cronofy.prototype.elevatedPermissions = function(){
  var details = this._parseArguments(arguments, ["access_token"]);

  return this._httpPost('/v1/permissions', details.options, details.callback);
}

cronofy.prototype.freeBusy = function(){
  var details = this._parseArguments(arguments, ["access_token"]);

  return this._httpGet(details.options.next_page || '/v1/free_busy', details.options, details.callback);
}

cronofy.prototype.listCalendars = function(){
  var details = this._parseArguments(arguments, ["access_token"]);

  return this._httpGet('/v1/calendars', details.options, details.callback);
}

cronofy.prototype.listNotificationChannels = function(){
  var details = this._parseArguments(arguments, ["access_token"]);

  return this._httpGet('/v1/channels', details.options, details.callback);
}

cronofy.prototype.profileInformation = function(){
  var details = this._parseArguments(arguments, ["access_token"]);

  return this._httpGet('/v1/profiles', details.options, details.callback);
}

cronofy.prototype.readEvents = function(){
  var details = this._parseArguments(arguments, ["access_token"]);

  return this._httpGet(details.options.next_page || '/v1/events', details.options, details.callback);
}

cronofy.prototype.refreshAccessToken = function(){
  var that = this;
  var details = this._parseArguments(arguments, ["client_id", "client_secret", "refresh_token"]);

  details.options.grant_type = "refresh_token";

  return this._httpPost('/oauth/token', details.options).then(tap(function(token){
    that.config.access_token = token.access_token;
    that.config.refresh_token = token.refresh_token;<commit_msg>fix(readevents): fix next page handling<commit_after>'use strict';

import _ from 'lodash';
import rest from './lib/rest-client';

var tap = function(func){
  return function(value){
    func.apply(null, arguments);
    return value;
  }
}

var cronofy = function(config){
  if(!this || this.constructor !== cronofy){
    throw new Error("Cronofy must be called as a constructor");
  }

  this.config = config;

  this.urls = {
    api: 'https://api' + (config.dataCenter ? '-' + config.dataCenter : '') + '.cronofy.com'
  };
}

cronofy.prototype._httpCall = function(method, path, options, callback, optionsToOmit){
  var settings = {
    method: method,
    path: this.urls.api + path,
    headers: {
      Authorization: 'Bearer ' + options.access_token,
      'Content-Type': 'application/json'
    },
    entity: _.omit(options, optionsToOmit || ['access_token'])
  };

  return new Promise(function(resolve, reject){
    rest(settings).then(function(result){
      if(callback){
        callback(null, result['entity']);
      } else {
        resolve(result['entity']);
      }
    }, function(err){
      var error = new Error(JSON.stringify(err.entity));
      if(err.status){
        error.statusCode = err.status.code;
      }

      if(callback){
        callback(error);
      } else {
        reject(error);
      }
    });
  });
}

cronofy.prototype._parseArguments = function(args, configDefaults){
  var parsed = {options: {}, callback: null};

  if(args.length == 2){
    parsed.options = args[0];
    parsed.callback = args[1];
  } else {
    switch(typeof args[0]){
      case "object":
        parsed.options = args[0];
        break;
      case "function":
        parsed.callback = args[0];
        break;
    }
  }

  for(var i = 0; i < configDefaults.length; i++){
    var key = configDefaults[i];

    parsed.options[key] = parsed.options[key] || this.config[key];
  }

  return parsed;
}

cronofy.prototype._httpGet = function(path, options, callback, optionsToOmit){
  return this._httpCall('GET', path, options, callback, optionsToOmit);
}

cronofy.prototype._httpPost = function(path, options, callback, optionsToOmit){
  return this._httpCall('POST', path, options, callback, optionsToOmit);
}

cronofy.prototype._httpDelete = function(path, options, callback, optionsToOmit){
  return this._httpCall('DELETE', path, options, callback, optionsToOmit);
}

cronofy.prototype.accountInformation = function(){
  var details = this._parseArguments(arguments, ["access_token"]);

  return this._httpGet('/v1/account', details.options, details.callback);
}

cronofy.prototype.addToCalendar = function(){
  var details = this._parseArguments(arguments, ["client_id", "client_secret"]);

  return this._httpPost('/v1/add_to_calendar', details.options, details.callback);
}

cronofy.prototype.authorizeWithServiceAccount = function(){
  var details = this._parseArguments(arguments, ["access_token"]);

  return this._httpPost('/v1/service_account_authorizations', details.options, details.callback);
}

cronofy.prototype.availability = function(){
  var details = this._parseArguments(arguments, ["access_token"]);

  return this._httpPost('/v1/availability', details.options, details.callback);
}

cronofy.prototype.createEvent = function(){
  var details = this._parseArguments(arguments, ["access_token"]);

  return this._httpPost('/v1/calendars/' + details.options.calendar_id + '/events', details.options, details.callback, ['access_token', 'calendar_id']);
}

cronofy.prototype.createNotificationChannel = function(){
  var details = this._parseArguments(arguments, ["access_token"]);

  return this._httpPost('/v1/channels', details.options, details.callback);
}

cronofy.prototype.deleteEvent = function(){
  var details = this._parseArguments(arguments, ["access_token"]);

  return this._httpDelete('/v1/calendars/' + details.options.calendar_id + '/events', details.options, details.callback, ['access_token', 'calendar_id']);
}

cronofy.prototype.deleteExternalEvent = function(){
  var details = this._parseArguments(arguments, ["access_token"]);

  return this._httpDelete('/v1/calendars/' + details.options.calendar_id + '/events', details.options, details.callback, ['access_token', 'calendar_id']);
}

cronofy.prototype.deleteNotificationChannel = function(){
  var details = this._parseArguments(arguments, ["access_token"]);

  return this._httpDelete('/v1/channels/' + details.options.channel_id, details.options, details.callback, ['access_token', 'channel_id']);
}

cronofy.prototype.elevatedPermissions = function(){
  var details = this._parseArguments(arguments, ["access_token"]);

  return this._httpPost('/v1/permissions', details.options, details.callback);
}

cronofy.prototype.freeBusy = function(){
  var details = this._parseArguments(arguments, ["access_token"]);

  return this._httpGet(details.options.next_page || '/v1/free_busy', details.options, details.callback);
}

cronofy.prototype.listCalendars = function(){
  var details = this._parseArguments(arguments, ["access_token"]);

  return this._httpGet('/v1/calendars', details.options, details.callback);
}

cronofy.prototype.listNotificationChannels = function(){
  var details = this._parseArguments(arguments, ["access_token"]);

  return this._httpGet('/v1/channels', details.options, details.callback);
}

cronofy.prototype.profileInformation = function(){
  var details = this._parseArguments(arguments, ["access_token"]);

  return this._httpGet('/v1/profiles', details.options, details.callback);
}

cronofy.prototype.readEvents = function(){
  var details = this._parseArguments(arguments, ["access_token"]);

  if (details.options.next_page && details.options.next_page.startsWith(this.urls.api)) {
    details.options.next_page = details.options.next_page.substr(this.urls.api.length);
  }

  return this._httpGet(details.options.next_page || '/v1/events', details.options, details.callback);
}

cronofy.prototype.refreshAccessToken = function(){
  var that = this;
  var details = this._parseArguments(arguments, ["client_id", "client_secret", "refresh_token"]);

  details.options.grant_type = "refresh_token";

  return this._httpPost('/oauth/token', details.options).then(tap(function(token){
    that.config.access_token = token.access_token;
    that.config.refresh_token = token.refresh_token;
{'fraction_non_alphanumeric': 0.1499638350880013, 'fraction_numerical': 0.00353612472876316, 'mean_word_length': 4.71875, 'pattern_counts': {'":': 4, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1143282', 'n_tokens_mistral': 3809, 'n_tokens_neox': 3746, 'n_words': 704}