text: /*!
   * Copyright 2014 Apereo Foundation (AF) Licensed under the
   * Educational Community License, Version 2.0 (the "License"); you may
   * not use this file except in compliance with the License. You may
   * obtain a copy of the License at
   *
   *     http://opensource.org/licenses/ECL-2.0
   *
   * Unless required by applicable law or agreed to in writing,
   * software distributed under the License is distributed on an "AS IS"
   * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
   * or implied. See the License for the specific language governing
   * permissions and limitations under the License.
   */
  
  define(['jquery', 'oae.core', 'activityadapter'], function($, oae, ActivityAdapter) {
  
      return function(uid, showSettings) {
  
          // Cache the widget container
          var $rootel = $('#' + uid);
  
  
          ////////////////////
          // Initialization //
          ////////////////////
  
          /**
           * Initialize the top navigation by setting up all of the menu items, submenus and
           * institutional logos
           */
          var initTopNavigation = function() {
              initLeftMenu();
              initRightMenu();
              initInstitutionalLogo();
          };
  
          /**
           * Initialize the left hand side of the navigation. There will be different options for logged in and logged out
           * users
           */
          var initLeftMenu = function() {
              var $template = oae.data.me.anon ? $('#topnavigation-left-anonymous-template') : $('#topnavigation-left-loggedin-template');
              oae.api.util.template().render($template, null, $('#topnavigation-left', $rootel));
          };
  
          /**
           * Initialize the right hand side of the top navigation. For anonymous users, this will contain a Sign In link
           * and Sign in dropdown. For logged in users, this will show the logout button
           */
          var initRightMenu = function() {
              if (oae.data.me.anon) {
                  $('#topnavigation-right', $rootel).append(oae.api.util.template().render($('#topnavigation-right-anonymous-template', $rootel), {
                      'enabledStrategies': oae.api.authentication.getEnabledStrategies(),
                      'redirectUrl': getLoginRedirectURL()
                  }));
              } else {
                  $('#topnavigation-right', $rootel).append(oae.api.util.template().render($('#topnavigation-right-loggedin-template', $rootel)));
              }
          };
  
          /**
           * Render the institutional logos. There will be a small logos that is displayed on small screen resolutions
           * and a large logo that will be displayed on larger screens
           */
          var initInstitutionalLogo = function() {
              oae.api.util.template().render($('#topnavigation-institutional-logo-template', $rootel), null, $('#topnavigation-institutional-logo-container', $rootel));
          };
  
          ////////////////////////
          // Push notifications //
          ////////////////////////
  
          /**
           * Subscribe to notification push notifications, allowing for notifications that happen after the initial
           * pageload to be reflected in the unread notifications count. Alternatively, when the notification widget
           * is already open, it can be the notifications stream straight away
           */
          var setUpPushNotifications = function() {
              if (!oae.data.me.anon) {
                  oae.api.push.subscribe(oae.data.me.id, 'notification', oae.data.me.signature, 'activitystreams', true, function(activity) {
  
                      // TODO: When the backend increases the notification count by aggregate, the UI should do the same
                      // See: https://github.com/oaeproject/Hilary/issues/566 has been implemented we should only increment the count
                      if (oae.data.me.notificationsUnread) {
                          oae.data.me.notificationsUnread += 1;
                      } else {
                          oae.data.me.notificationsUnread = 1;
                      }
  
                      // Update the unread notification count in the top navigation
                      $('#topnavigation-notification-count', $rootel).text(oae.data.me.notificationsUnread);
  
                      // Update the unread notifications favicon bubble
                      oae.api.util.favicon().setBubble(oae.data.me.notificationsUnread);
  
                      // Show a notification about the activity when the notifications popover is not visible
                      if ($('.oae-trigger-notifications + .popover:visible', $rootel).length === 0) {
                          var sanitization = oae.api.util.security();
                          var adaptedActivity = ActivityAdapter.adapt(oae.data.me.id, oae.data.me, [activity], sanitization)[0];
                          var notificationBody = oae.api.util.template().render($('#topnavigation-push-notification-summary', $rootel), {'activity': adaptedActivity});
                          oae.api.util.notification(null, notificationBody, null, activity['oae:activityType'] + '#' + activity.published);
                      }
                  });
              }
          };
  
          ///////////////////
          // Accessibility //
          ///////////////////
  
          /**
           * Set up the skip links that can be used by screenreader and keyboard users
           * to jump past the top navigation
           */
          var setUpSkipLinks = function() {
              // Focus on the target element when clicking
              // a skip link
              $rootel.on('click', '.oae-skip-link', function() {
                  $($(this).attr('href')).focus();
                  return false;
              });
          };
  
  
          ////////////
          // Search //
          ////////////
  
          /**
           * Set up the top navigation search form. When the form is submitted, the user will be
           * redirected to the search page using the entered search query
           */
          var setUpSearch = function() {
              $(document).on('submit', '#topnavigation-search-form', function() {
                  var query = $.trim($('#topnavigation-search-query', $(this)).val());
                  window.location = '/search/' + oae.api.util.security().encodeForURL(query);
                  return false;
              });
          };
  
  
          ///////////
          // Login //
          ///////////
  
          /**
           * Set up all login related functionality.
           */
          var setUpLogin = function() {
              $rootel.on('click', '#topnavigation-signin', function() {
                  // Set the cursor focus on the username field when opening the login dropdown. We have
                  // to set a timeout to make sure that bootstrap has finished showing the dropdown menu.
                  setTimeout(function() {
                      $('#topnavigation-signin-username').focus();
                  }, 1);
              });
  
              setUpLoginValidation();
          };
  
          /**
           * Get the URL to which the user should be redirected after signing in successfully. When a specific
           * login redirect target has been encoded in the URL, this target will always be used as the redirect.
           * When no explicit target is present, the current page will be reloaded unless the user is currently
           * on the landing page. In that case, the user will be redirected to his personal landing page.
           */
          var getLoginRedirectURL = function() {
              var currentLocation = window.location.pathname;
              // If a `url` parameter is available in the URL, use this as the redirect URL
              if ($.url().param('url')) {
                  return $.url().param('url');
              // When on the landing page, use the me page as the redirect URL
              } else if (window.location.pathname === '' || window.location.pathname === '/') {
                  return '/me';
              // On all other pages, redirect back to the current page
              } else {
                  return currentLocation;
              }
          };
  
          /**
           * Add validation to the login form
           */
          var setUpLoginValidation = function() {
              var $loginForm = $('#topnavigation-signin-form', $rootel);
              var validateOpts = {
                  'messages': {
                      'topnavigation-signin-username': {
                          'required': oae.api.i18n.translate('__MSG__PLEASE_ENTER_YOUR_USERNAME__'),
                          'topnavigation-failed-attempt': oae.api.i18n.translate('__MSG__INVALID_USERNAME_OR_PASSWORD__')
                      },
                      'topnavigation-signin-password': oae.api.i18n.translate('__MSG__PLEASE_ENTER_YOUR_PASSWORD__')
                  },
                  'methods': {
                      'topnavigation-failed-attempt': {
                          'method': function(value, element) {
                              // This class will be added after a failed login attempt and is used
                              // to tell jquery.validate to mark the field as invalid
                              return false;
                          }
                      }
                  },
                  'submitHandler': doLogin
              };
              oae.api.util.validation().validate($loginForm, validateOpts);
          };
  
          /**
           * Attempt to log in the user with the provided username and password onto the current tenant using either
           * the LDAP login strategy or the local login strategy. If only one of them is enabled, only that strategy
           * will be attempted. If both of them are enabled, an LDAP login will be attempted first. If that is unsuccessful,
           * a local login will be attempted next. This function will only be executed when form validation has passed.
           */
          var doLogin = function() {
              // Hide the login button and show a logging in message
              $('#topnavigation-signin-button', $rootel).show();
              $('#topnavigation-signin-signing-in', $rootel).hide();
  
              // Check whether or not the LDAP login strategy is enabled
              var LDAPEnabled = oae.api.config.getValue('oae-authentication', 'ldap', 'enabled');
              // Check whether or not the local login strategy is enabled
              var LocalEnabled = oae.api.config.getValue('oae-authentication', 'local', 'enabled');
  
              // Get the entered username and password
              var username = $.trim($('#topnavigation-signin-username', $rootel).val());
              var password = $.trim($('#topnavigation-signin-password', $rootel).val());
  
              // Both LDAP and local are enabled. We try LDAP first, and try local next if LDAP has failed
              if (LDAPEnabled && LocalEnabled) {
                  oae.api.authentication.LDAPLogin(username, password, function(err) {
                      if (err) {
                          oae.api.authentication.localLogin(username, password, finishLogin);
                      } else {
                          finishLogin();
                      }
                  });
              // Only LDAP is enabled
              } else if (LDAPEnabled) {
                  oae.api.authentication.LDAPLogin(username, password, finishLogin);
              // Only local authentication is enabled
              } else {
                  oae.api.authentication.localLogin(username, password, finishLogin);
              }
          };
  
          /**
           * Finish the login process by showing the correct validation message in case of a failed
           * login attempt, or by redirecting the user in case of a successful login attempt
           *
           * @param  {Error}      err        Error object containing error code and error message
           */
          var finishLogin = function(err) {
              if (err) {
                  // Show the login button again
                  $('#topnavigation-signin-signing-in', $rootel).hide();
                  $('#topnavigation-signin-button', $rootel).show();
                  // Set a `topnavigation-failed-attempt` on the fields to tell jquery.validate
                  // that the field is invalid
                  $('#topnavigation-signin-username', $rootel).addClass('topnavigation-failed-attempt');
                  $('#topnavigation-signin-form', $rootel).valid();
                  $('#topnavigation-signin-username', $rootel).removeClass('topnavigation-failed-attempt');
                  // Clear the password field
                  $('#topnavigation-signin-password', $rootel).val('');
                  // Focus into the username field
                  $('#topnavigation-signin-username', $rootel).focus();
              } else {
                  // Get the URL to which we should be redirected after logging in
                  var redirectURL = getLoginRedirectURL();
                  // If the redirect URL is the same as the current URL, we refresh the page
                  if (redirectURL === window.location.pathname) {
                      window.location.reload(true);
                  } else {
                      window.location = redirectURL;
                  }
              }
          };
  
          initTopNavigation();
          setUpLogin();
          setUpSkipLinks();
          setUpSearch();
          setUpPushNotifications();
  
      };
  });
  
  