//
// Copyright 2009-2010 Electronic Arts, Inc.
//

//
// Dependencies
//
// This library depends on (with the following inclusion order): 
// - "/fbconnect/js.do"
//


/**
 * Set of helper methods to be used to interact with facebook.
 */
var PogoFB = PogoFB || {
  _apiInitialized: false,
  _initialized: false,

  /**
   * Initializes the Facebook API.
   */
  initializeFB: function() {
    if (PogoFB._apiInitialized) {
      return;
    }
    FB_RequireFeatures(["Api", "XFBML", "Connect"], function() {  
        FB.init(PogoFBConstants.apiKey, "/fbconnect/xd_receiver.htm",
            {"ifUserConnected" : function () {PogoFB._onStatusChange(false);},
            "ifUserNotConnected" : function () {PogoFB._onStatusChange(false);} });
        }
    );
    PogoFB._apiInitialized = true;
  },

  /**
   * Array to store the functions that should be invoked on initialization.
   */
  onInitialize: new Array(),

  /**
   * Function that calls any function stored into onInitialize array.
   */
  _initialize: function() {
    if (PogoFB._initialized) {
      return;
    }
    for (var i = 0; i < PogoFB.onInitialize.length; i++) {
      PogoFB.onInitialize[i]();
    }
    PogoFB._initialized = true;   
  },

  /**
   * Array to store the functions that should be invoked when the status is
   * verified so that the enclosing page can adapt to the new status.
   *
   * Functions pushed onto this array can optionally take as a parameter the
   * status details (a JSON representation of
   * com.pogo.html.struts.fbconnect.FacebookConnectStatusDetails).
   */
  onStatusValidation: new Array(),

  onConnectCallback: null,

  /**
   * Function to be called as a callback on the FB.init method call, if a user
   * is connected. This function invokes all the functions that have been pushed
   * to the onStatusValidation array.
   */
  _onStatusChange: function(showErrorPopup) {
    PogoFB._initialize();
    PogoFB.Status.getStatus(function(status) {
      for (var i = 0; i < PogoFB.onStatusValidation.length; i++) {
        PogoFB.onStatusValidation[i](status);
      }
      if (status.connected && !status.newLink) {
        if (typeof PogoFB.onConnectCallback == 'function') {
          PogoFB.onConnectCallback();
          PogoFB.onConnectCallback = null;
        }
      }
    }, showErrorPopup);
  },

  /**
   * Function that calls any function stored into onNewLinkFunctions array.
   */
  onNewLink: function() {
    if (typeof PogoFB.onConnectCallback == 'function') {
      PogoFB.onConnectCallback();
      PogoFB.onConnectCallback = null;
    }
  },

  /**
   * Method to request the current user to login. This method assumes that it
   * is not invoked if the current pogo user and facebook user are already
   * linked.
   */
  login: function() {
    if (window.ie6) {
      PogoFB.Popover.show('/fbconnect/upgradebrowser.do');
    } else {
      PogoFB._Link.createLink();
    }
  },

  /**
   * Function that calls FB API to show FB authentication popup.
   */
  requireSession: function() {
    PogoFB.login();
  },

  /**
   * Method that logs out per request the current facebook user and asks the
   * user to log back in to facebook (with a different user).
   */
  logout: function() {
    FB.Connect.logout(function() {
      PogoFB._Link.createLink();
    });
  },

  /**
   * Method to remove the link between the facebook and pogo user. It shows a 
   * confirmation popover and if the user confirms the link is removed.
   *
   * TODO(cdolan): Figure out how to make this look more elegant.
   */
  removeLink: function(omnitureMessage) {
    var onclickFunctions = "PogoFB.Popover.close(this);PogoFB._Link.remove();"
    if (omnitureMessage) {
      onclickFunctions = "PogoFB.Utils.omnitureTagging('" + omnitureMessage + "'); " + onclickFunctions;
    }
    
    PogoFB.Popover.showContent(
        '<div id="mdBox">'
        + '<div class="hdr">'
        +   '<img src="/img/fbconnect/popover/hd-lt-cnr.gif" class="inl" />'
        +   '<h3 class="inl">'
        +   PogoFBConstants.Messages.removeLinkConfirmTitle
        +   '</h3>'
        +   '<img src="/img/fbconnect/popover/hd-rt-cnr.gif" class="inl-r" />'
        +   '<div class="clear"></div>'
        + '</div>'
        + '<div class="withfblogo">'
        +    '<img src="/img/fbconnect/facebook-logo.gif" class="inl firstBtn" />'
        +    '<div class="desc inl">'
        +      PogoFBConstants.Messages.removeLinkConfirmMessage
        +    '</div>'
        +    '<div class="clear"></div>'
        +  '</div>'
        +  '<div class="ftr">'
        +    '<a href="javascript:void(0);" onclick="' + onclickFunctions + '">'
        +      PogoFBConstants.Images.disconnectButton
        +    '</a>'
        +    '<a href="javascript:void(0);" onclick="PogoFB.Popover.close(this)">'
        +      PogoFBConstants.Images.cancelButton
        +    '</a>'
        +  '</div>'
        +  '</div>', false);
  },

  saveSettings: function(settingsForm) {
    var url = "/fbconnect/settings/save.do?facebookProfileVisible=" + settingsForm.elements['facebookProfileVisible'].checked;
    MootoolsUtils.request(url, {
      method: 'get',
      onSuccess: function(responseText){
        // nothing...
      },
      onFailure: PogoFB.Error.showServerErrorPopUp
   });
  },

  /**
   * Wrapper that ensures that the given callback will be invoked if and only
   * if the user has connected, and prompts the user to connect if he hasn't.
   */
  requireConnected: function(callback, connectRequestedTag) {
    PogoFB.Status.getStatus(function (status) {
      if (status.connected) {
        callback();
      } else {
        PogoFB.onConnectCallback = callback;
        if (!status.isPogoUserLinked) {
          if (connectRequestedTag) {
            PogoFB.Utils.omnitureTagging(connectRequestedTag);
          }
        }
        PogoFB.login();
      }
    });
  },

  hasAutopublishPermission: function (callbackOnSuccess,callbackOnFail) {
    if (!PogoFBConstants.autoshareEnabled) {
      if ( typeof callbackOnFail =='function') {
          callbackOnFail();
        }
        return;
    }
    else {
      FB.Facebook.apiClient. users_hasAppPermission('publish_stream', function(result){
        if (result == 1 ) {
          if ( typeof callbackOnSuccess =='function') {
            callbackOnSuccess();
         }
        } else {
          if ( typeof callbackOnFail =='function') {
            callbackOnFail();
         }
        }
        });
    }
  },

  /**
   * Wrapper that ensures that the given callback will be invoked if and only
   * if the user has the required permission or grants it upon the request.
   */
  requirePermission: function(permission, callback, page) {
    FB.Facebook.apiClient. users_hasAppPermission(permission, function(result){
      if (result == 1 ) {
      // user already has permission
        if ( typeof callback =='function') {
          callback();
        }
      } else {
        // track init autopublish grant 
    PogoFB.Utils.omnitureTagging(PogoFB._getInitPermissionOmnitureTag(page));
        FB.Connect.showPermissionDialog(permission, function (grantedPermissions) {
          if (grantedPermissions != null && typeof grantedPermissions.indexOf == 'function'
            && grantedPermissions.indexOf(permission) >= 0 ) {
            //if permission has been granted
            if (typeof callback =='function') {
              callback();
            }
            PogoFB.Utils.omnitureTagging(PogoFB._getConfirmedPermissionOmnitureTag(page));
          }
          else {
          //If permission has been rejected 
            PogoFB.Utils.omnitureTagging(PogoFB._getRejectedPermissionOmnitureTag(page));
          }
        }, false, []);
      }
    });    
  },
  
   _getInitPermissionOmnitureTag: function(publishType) {
    if (publishType == 'popup') {
        return PogoFBConstants.Messages.popupSettingsInitAutopublish;
      } else {
        return PogoFBConstants.Messages.defaultSettingsInitAutopublish; 
      }
   },
   
   _getConfirmedPermissionOmnitureTag: function(publishType) {
    if (publishType == 'popup') {
        return PogoFBConstants.Messages.popupSettingsDoAutopublish;
      } else {
        return PogoFBConstants.Messages.defaultSettingsDoAutopublish; 
      }
   },
   _getRejectedPermissionOmnitureTag: function(publishType) {
    if (publishType == 'popup') {
        return PogoFBConstants.Messages.popupSettingsRejectAutopublish;
      } else {
        return PogoFBConstants.Messages.defaultSettingsRejectAutopublish; 
      }
   },

   /**
   * Wrapper that removes the autopublish permission.
   */
   removeAutoPublishPermission: function(callbackIfSuccess, callbackIfFail) {
    var url = "/fbconnect/removeextperm.do";
    MootoolsUtils.request(url, {
          method: 'get',
          onSuccess: function(responseText){
          PogoFB.Utils.omnitureTagging(PogoFBConstants.Messages.settingsRemoveAutopublish);
          callbackIfSuccess();
          },
          onFailure: function(){
            if (typeof callbackIfFail =='function') {
              callbackIfFail();
           } else {
            PogoFB.Error.showServerErrorPopUp();
           }
          }
       });
   }
};

/**
 * Helper methods to handle the status of the current user. This is done this
 * way to allow reusing the recently looked up status, rather than making
 * multiple ajax calls.
 */
PogoFB.Status = {
  _currentStatus: null,

  /**
   * Invokes the callback with the _currentStatus. If none has been set as
   * current, it invokes an action to get the current one.
   */
  getStatus: function(callback, showErrorPopup) {
    if (PogoFB.Status._currentStatus != null ) {
      callback(PogoFB.Status._currentStatus);
      return;
    }

    var shouldShowError = typeof showErrorPopup == 'undefined' || showErrorPopup;
    MootoolsUtils.request("/fbconnect/getstatus.do", {
      method: 'get',
      onSuccess: function(responseText){
        PogoFB.Status._currentStatus = eval(responseText);
        callback(PogoFB.Status._currentStatus);
      },
      onFailure: function() {
        if (shouldShowError) {
          PogoFB.Error.showServerErrorPopUp();
        }
      }
   });
  },

  /**
   * Updates the current status object.
   */
  updateCurrentStatus: function(status) {
    PogoFB.Status._currentStatus = status;
  }
};

/**
 * Handler for error messages.
 */
PogoFB.Error = {

  /**
   * Generic error messaage shown within a popup. Hardcoded to be used as a
   * generic error popup.
   *
   * TODO(cdolan): Figure out how to make this look more elegant.
   */
  showServerErrorPopUp: function() {
    PogoFB.Popover.showContent(
        '<div id="mdBox">'
        + '<div class="hdr">'
        +   '<img src="/img/fbconnect/popover/hd-lt-cnr.gif" class="inl" />'
        +   '<h3 class="inl">'
        +   PogoFBConstants.Messages.errorInternalTitle
        +   '</h3>'
        +   '<img src="/img/fbconnect/popover/hd-rt-cnr.gif" class="inl-r" />'
        +   '<div class="clear"></div>'
        + '</div>'
        + '<div class="withfblogo">'
        +    '<img src="/img/fbconnect/facebook-logo.gif" class="inl firstBtn" />'
        +    '<div class="desc inl">'
        +      PogoFBConstants.Messages.errorFatalAjaxProblem
        +    '</div>'
        +    '<div class="clear"></div>'
        +  '</div>'
        +  '<div class="ftr">'
        +    '<a href="javascript:void(0)" onclick="PogoFB.Popover.close(this)">'
        +      PogoFBConstants.Images.cancelButton
        +    '</a>'
        +  '</div>'
        +  '</div>', true);
  }
};

/**
 * Set of methods associated to user linkage.
 */
PogoFB._Link = {

  /**
   * Attempts to create a link between the current pogo user and the facebook
   * user (if none login, requires a login). This method assumes that it is not
   * invoked if the current pogo user and facebook user are already linked.
   */
  createLink: function() {
    FB.Connect.get_status().waitUntilReady( function(fbstatus) {
      switch (fbstatus) {
        case FB.ConnectState.connected:
          PogoFB.Status.getStatus(function(status) {
            // three conditions may occur here:
            // - the pogo user has a link and he's attempting to log in with
            //   another facebook user which means we must show the users
            //   mismatch error
            // - the current fb user is linked to someone else, and the current
            //   pogo user is trying to create a link to him; in this case we
            //   must show the already connected error
            // - the current fb user has granted the app but the link was
            //   removed (though not the grant), therefore the user is free to
            //   be linked, we try to go through the linking process
            if (status.connected) {
              // nothing to do
            } else if (status.isPogoUserLinked) {
              PogoFB.Popover.show('/fbconnect/error/usersmismatch.do');
            } else if (status.isFbUserLinked) {
              PogoFB.Popover.show('/fbconnect/error/alreadyconnected.do');
            } else {
              PogoFB._Link.callLinkAction();
            }
          });
          break;

        // request a login and attempt to link both users
        case FB.ConnectState.userNotLoggedIn:
        case FB.ConnectState.appNotAuthorized:
          FB.Connect.requireSession(PogoFB._Link.callLinkAction);
          break;
      }
    });
  },

  /**
   * Effectively invokes the action that creates the link between the two users.
   */
  callLinkAction: function() {
    MootoolsUtils.request("/fbconnect/link.do", {
        method: 'get',
        onSuccess: function(responseText){
          var status = eval(responseText);

          // status may have changed, so we have to update it
          PogoFB.Status.updateCurrentStatus(status);

          if (!status.connected && status.isPogoUserLinked) {
            PogoFB.Popover.show('/fbconnect/error/usersmismatch.do');
          } else if (!status.connected && status.isFbUserLinked) {
            PogoFB.Popover.show('/fbconnect/error/alreadyconnected.do');
          }

          PogoFB._onStatusChange();

          // if it is a new link, we must show the settings dialog
          //if it is a new link then trigger a new omniture event to track
          //event10 == FACEBOOK_ACCT_LINK
          if (status.newLink) {
              if (typeof OmnitureEvent == 'function') {
                OmnitureEvent(s.pageName, 'event10');
              }
              PogoFB.Popover.show('/fbconnect/settings/showdialog.do');
          }
        },
        onFailure: PogoFB.Error.showServerErrorPopUp
    });

  },

  /**
   * Action that removes the link between the current facebook and pogo user.
   */
  remove: function() {
    MootoolsUtils.request("/fbconnect/removelink.do", {
        method: 'get',
        onSuccess: function(responseText){
          window.location = responseText;
        },
        onFailure: PogoFB.Error.showServerErrorPopUp
    });
  }
};

PogoFB.Popover = {

  show: function(url) {
    if (PogoFB.Popover.current) {
      // FB has a minor bug by which once a function is passed on to the require
      // session it will remain there. Therefore, if the user clicks on the
      // connect button, closes the window and clicks back on it, the
      // _callLinkAction will be invoked twice, and that could result in
      // duplicate popups
      return;
    }
    MootoolsUtils.request(url, {
        method: 'get',
        onSuccess: function(responseText){
          PogoFB.Popover.current =  new Popover(responseText);
        },
        onFailure: PogoFB.Error.showServerErrorPopUp,
        evalScripts:true
    });
  },

  showContent: function(innerHTML, forceClose) {
    if (PogoFB.Popover.current) {
      // FB has a minor bug by which once a function is passed on to the require
      // session it will remain there. Therefore, if the user clicks on the
      // connect button, closes the window and clicks back on it, the
      // _callLinkAction will be invoked twice, and that could result in
      // duplicate popups
      if (!forceClose) {
        return;
      }
      PogoFB.Popover.close();
    }
    PogoFB.Popover.current = new Popover(innerHTML);
  },

  close: function(element) {
    if (element) {
      Popover.close(element);
      PogoFB.Popover.current = null;
    } else {
      if (PogoFB.Popover.current) {
        PogoFB.Popover.current.closeModal();
        PogoFB.Popover.current = null;
      }
    }
  }
};

/**
 * Set of utility methods.
 */
PogoFB.Utils = {

  /**
   * Method that returns the html to be used to display the login button,
   * instead of Facebook's standard fbml tag. 
   */
  getLoginButtonHtml: function(id) {
    var htmlString = 
        '<a href="javascript:void(0);" onclick="PogoFB.login();" id="' + id + '" >'
        + '<img id="fb_login_image" src="http://static.ak.fbcdn.net/images/fbconnect/login-buttons/connect_light_medium_long.gif" '
        + 'alt="'
        + PogoFBConstants.Messages.commonConnect
        + '"/>'
        + '</a>';
    return htmlString;
  },

  /**
   * Adds the omniture tagging to the given element's onclick event.
   */ 
  tagOnClick: function(element, message) {
    $(element).addEvent('click', function() {
      PogoFB.Utils.omnitureTagging(message);
    });
  },

  /*
   * @deprecated: Is about to be gone. Must use _addSourceId instead.
   */
  _addExternSrc: function(url, tag) {
    return PogoFB.Utils._addParam(url,'sourceid',tag)
  },

  _addSourceId: function(url, tag) {
    return PogoFB.Utils._addParam(url,'sourceid',tag)
  },

  _addParam: function(url, param, value) {
    if (url.indexOf('?') < 0) {
      return url + '?' + param + '=' + value;
    } else {
      return url + '&' + param + '=' + value;
    }
  },
  
  /**
   * Sets the omniture tagging for a custom action.
   *
   * Preconditions: omniture s_gi function must be declared in the page that calls this utility class.
   */ 
  omnitureTagging: function(message, events) {
    if (events) {
      if (typeof OmnitureEvent == 'function') {
        OmnitureEvent(message, events);
      }  
    } else {
      if(typeof OmnitureCustomLink == 'function') {
        OmnitureCustomLink(message);
      }
    }
  }, 
  
  /**
   * Parses the DOM tree to reflect Facebook XFBML dynamic changes and
   * after all elements are ready it executes the callback function.
   */
  parseDom: function(callback) {
    FB.XFBML.Host.parseDomTree();
    if (callback) {
      FB.XFBML.Host.get_areElementsReady().waitUntilReady(callback);
    }
  },

  /**
   * Returns the link with the standard 'What's this' message, that opens the
   * FAQ as a popover.
   */
  getFaqLink: function() {
    var htmlString = 
        '<a href="javascript:void(0)" onclick="var win = window.open(\'/fbconnect/faq.do\', \'PogoFbHelp\', \'width=600,height=460,location=no,resizable=yes,toolbar=no,scrollbars=yes\');if (win) win.focus();" >'
        + PogoFBConstants.Messages.commonWhatIsThis
        + '</a>';
    return htmlString;
  },

  /**
   * Opens a pop up extracting the data from the anchor element received.
   */
  openInviteFriendsPopUp: function() {
    window.open(PogoFBConstants.URLs.inviteFriends,
        '_blank', 'width=800px,height=600px');
  }
}

/**
 * Formats a message following java's MessageFormat behavior.
 */
var MsgFormat = MsgFormat || {
  format: function(s) {
    var i = 1;
    while (i < arguments.length) {
      s = s.replace("{" + (i-1) + "}", arguments[i++]);
    }
    return s;
  }
}

/**
 * Add an event so that the Facebook Api is initialized as soon as the DOM is
 * ready.
 */
if (PogoFBConstants.facebookEnabled) {
window.addEvent('domready', function() {
    PogoFB.initializeFB();
});
}

