text: /*!
   * Copyright 2013 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.
   */
  
  var assert = require('assert');
  var ShortId = require('shortid');
  var util = require('util');
  
  var RestAPI = require('oae-rest');
  var TestsUtil = require('oae-tests/lib/util');
  
  /**
   * Set up 2 public tenants and 2 private tenants, each with a public, loggedin, private set of users and
   * discussions. The resulting model looks like:
   *
   * ```
   *  {
   *      "publicTenant": {
   *          "tenant": <Tenant>,
   *          "anonymousRestCtx": <RestContext>,
   *          "adminRestCtx": <RestCOntext> (of the tenant admin),
   *          "publicDiscussion": <Discussion>,
   *          "loggedinDiscussion": <Discussion>,
   *          "privateDiscussion": <Discussion>,
   *          "publicUser": {
   *              "user": <User>,
   *              "restCtx": <RestContext>
   *          },
   *          "loggedinUser": { ... }
   *          "privateUser": { ... }
   *      },
   *      "publicTenant1": { ... },
   *      "privateTenant": { ... },
   *      "privateTenant1": { ... }
   *  }
   * ```
   *
   * @param  {Function}   Invoked when all the entities are set up
   * @throws {Error}      An assertion error is thrown if something does not get created properly
   */
  var setupMultiTenantPrivacyEntities = module.exports.setupMultiTenantPrivacyEntities = function(callback) {
      // Create the tenants and users
      TestsUtil.setupMultiTenantPrivacyEntities(function(publicTenant, publicTenant1, privateTenant, privateTenant1) {
          // Create the discussions.
          _setupTenant(publicTenant, function() {
              _setupTenant(publicTenant1, function() {
                  _setupTenant(privateTenant, function() {
                      _setupTenant(privateTenant1, function() {
                          return callback(publicTenant, publicTenant1, privateTenant, privateTenant1);
                      });
                  });
              });
          });
      });
  };
  
  /**
   * Create the discussions within a tenant.
   *
   * @param  {Tenant}     tenant          The tenant to setup
   * @param  {Function}   callback        Invoked when all the entities are set up
   * @throws {Error}                      An assertion error is thrown if something does not get created properly
   * @api private
   */
  var _setupTenant = function(tenant, callback) {
      _createMultiPrivacyDiscussions(tenant.adminRestCtx, function(publicDiscussion, loggedinDiscussion, privateDiscussion) {
          tenant.publicDiscussion = publicDiscussion;
          tenant.loggedinDiscussion = loggedinDiscussion;
          tenant.privateDiscussion = privateDiscussion;
          callback();
      });
  };
  
  /**
   * Set up discussions of all privacies using the given rest context
   *
   * @param  {RestContext}    restCtx         The rest context to use
   * @param  {Function}       callback        Invoked when all the entities are set up
   * @throws {Error}                          An assertion error is thrown if something does not get created properly
   * @api private
   */
  var _createMultiPrivacyDiscussions = function(restCtx, callback) {
      _createDiscussionWithVisibility(restCtx, 'public', function(publicDiscussion) {
          _createDiscussionWithVisibility(restCtx, 'loggedin', function(loggedinDiscussion) {
              _createDiscussionWithVisibility(restCtx, 'private', function(privateDiscussion) {
                  return callback(publicDiscussion, loggedinDiscussion, privateDiscussion);
              });
          });
      });
  };
  
  /**
   * Create a discussion with the specified visibility
   *
   * @param  {RestContext}    restCtx             The rest context to use
   * @param  {String}         visibility          The visibility of the user
   * @param  {Function}       callback            Invoked when all the entities are set up
   * @param  {Discussion}     callback.discussion The discussion that was created
   * @throws {Error}                              An assertion error is thrown if something does not get created properly
   * @api private
   */
  var _createDiscussionWithVisibility = function(restCtx, visibility, callback) {
      var randomId = util.format('%s-%s', visibility, ShortId.generate());
      RestAPI.Discussions.createDiscussion(restCtx, 'displayName-' + randomId, 'description-' + randomId, visibility, null, null, function(err, discussion) {
          assert.ok(!err);
          return callback(discussion);
      });
  };
  