this.SK = this.SK || {};

// MUST publish events: cancel, login, signup

SK.Facebook = {
  REQUIRED_PERMISSIONS: ['email'],
  UI_INIT: false,

  init: function(appId, options) {
    options = options || {};
    FB.init({ appId: appId, cookie: true });

    this._appId      = appId;
    this._options    = options || {};
    this._callbacks  = [];
    this._hasSession = false;
    this._connecting = false;
    this._successUrl = this._options.successUrl;

    this._grantedPermissions = [];

    var self = this, handleAuth = function(response) {
      self._handleAuthChange(response);
      self._options.autoLogin = false;
    };

    FB.Event.subscribe('auth.sessionChange', handleAuth);
    FB.getLoginStatus(handleAuth);
  },

  _handleAuthChange: function(response) {
    this._hasSession = !!response.session;

    if (this._hasSession && this._options.autoLogin)
      this.login();
  },

  _succeed: function() {
    var callbacks = this._callbacks, listener;

    for (var i = 0, n = callbacks.length; i < n; i++) {
      listener = callbacks[i];
      listener[0].apply(listener[1], arguments);
    }
    this._callbacks = [];
  },

  connect: function(callback, scope) {
    if (this._hasSession) return callback.call(scope, this._grantedPermissions);

    this._callbacks.push([callback, scope]);
    if (this._connecting) return;

    var permissions = {perms: this.REQUIRED_PERMISSIONS.join(',')},
        self = this;

    this._connecting = true;

    FB.login(function(response) {
      self._connecting = false;

      if (!response.session) return self.trigger('cancel');
      if (!response.perms) return;

      setFBCookie(response, self._appId);

      self._grantedPermissions = response.perms.split(',');
      self._succeed(self._grantedPermissions);

    }, permissions);
  },

  // Execute a set of API calls in parallel and
  // collate the results for a single callback
  request: function(apiCalls, callback, scope) {
    this.connect(function() {
      var results = {},
      complete = 0,
      expected = 0;

      var requestResource = function(key, url) {
        FB.api(url, function(response) {
          results[key] = response;
          complete += 1;
          if (complete === expected) callback.call(scope, results);
        });
      };

      for (var key in apiCalls) {
        expected += 1;
        requestResource(key, apiCalls[key]);
      }
    }, this);
  },

  getUserDetails: function(callback, scope) {
    this.request({me: '/me', friends: '/me/friends'}, function(results) {
      var me = results.me;
      me.friends = jQuery.map(results.friends.data, function(f) { return f.id });
      callback.call(scope, me);
    });
  },

  login: function(callback, scope) {
    this.getUserDetails(function(details) {
      // Posting empty data to our backend causes a 500. These empty returns from Facebook
      // are usually duplicates that coincide with a working call, so the user will be
      // logged in. We should just ignore empty sets of return data - JC 8 July 2010
      if (!details.id) return;

      var data = {
        facebook_id:    details.id,
        email:          details.email,
        name:           details.first_name + ' ' + details.last_name,
        friends:        details.friends.join(','),
        required_perms: SK.Facebook.REQUIRED_PERMISSIONS.join(','),
        allowed_perms:  this._grantedPermissions.join(','),
        success_url:    this._successUrl
      };

      this.trigger('login');
      var self = this;

      jQuery.post('/sessions/fb/new', data, function(response) {
        if (response.new_user) self.trigger('signup');

        if (callback) return callback.call(scope, response);
        
        var url = response.url;
        if (!jQuery.trim(url)) url = window.location.href;
        window.location.href = url;
      }, 'json');

    }, this);
  },

  logout: function(callback, scope) {
    if (!this._hasSession) return callback.call(scope);
    FB.logout(function() { callback.call(scope) });
    return false;
  },

  logoutAndRedirect: function() {
    this.logout(function() {
      window.location.href = '/sessions/fb/destroy';
    });
    return true;
  },

  shareEvent: function(event) {
    SK.modality.close();
    this.login(function(user) {
      FB.ui({
        method:     'stream.publish',
        message:    '',
        attachment: this._attachmentFor(event),
        user_message_prompt: 'Tell your friends about ' + event.shortName
        
      }, function(response) {
        if (response && response.post_id)
          SK.Analytics.kmRecord('FB share event');
        else
          SK.Analytics.kmRecord('FB cancel sharing event');
        
        setTimeout(function() {
          var url = user.new_user ? '/tracker/recommendations' : window.location.href;
          window.location.href = url;
        }, 500);
      });
    }, this);
  },

  _attachmentFor: function(event) {
    var media = jQuery.map(event.images, function (image_path) {
      return {type: "image", src: image_path, href: event.url};
    });
    
    return {
      name:         event.name,
      caption:      event.caption,
      description:  event.description,
      href:         event.url,
      media:        media
    };
  }
};

SK.extend(SK.Facebook, SK.Evented);

