// Copyright 2011 Software Freedom Conservancy.
//
// Licensed under the Apache 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://www.apache.org/licenses/LICENSE-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.

/**
 * @fileoverview Defines a wrapper around {@link bot.inject.executeScript} so it
 * can be invoked via Selenium RC.
 */

goog.provide('core.inject');

goog.require('bot.dom');
goog.require('bot.inject');
goog.require('core.firefox');
goog.require('goog.array');
goog.require('goog.json');
goog.require('goog.object');


/**
 * @param {!{script:string, args:!Array.<*>}} json The executeScript parameters
 *     in the form of a JSON object.
 * @param {Window=} opt_window The window to execute the script in. Defaults to
 *     the window running this script.
 * @return {string} The stringified response object.
 * @see bot.inject.executeScript
 */
core.inject.executeScript = function(json, opt_window) {
  var result = bot.inject.executeScript(json['script'],
      core.inject.removeElementIdPrefix_(json['args']),
      false, opt_window || window);
  result = core.inject.addElementIdPrefix_(result);
  return goog.json.serialize(result);
};


/**
 * Adapts {@link bot.inject.executeScript} for use with Selenium RC. This
 * function is not exposed as a public API - instead it is intended to be called
 * by the Selenium-backed WebDriver via {@code Selenium.prototype.getEval}.
 * Consequently, function parameters are expected in the form of a JSON object,
 * which is easier to serialize when building the "getEval" command. This
 * object must have the following fields:
 * <ol>
 *   <li>script - A string for the script to execute.</li>
 *   <li>args - An array of script arguments.</li>
 *   <li>timeout - How long the script is permitted to run.</li>
 * </ol>
 *
 * @param {{script:string, args:!Array.<*>, timeout:number}} json The execute
 *     script parameters, in the form of a JSON object.
 * @return {{terminationCondition: function():boolean}} An object with a
 *     termination condition that may be polled by Selenium Core to determine
 *     when the script has finished execution.
 * @see bot.inject.executeAsyncScript
 */
core.inject.executeAsyncScript = function(json) {
  var isDone = false, result;

  // The terminationCondition is invoked in the context of an AccessorResult
  // object.  When the script finishes, this function will marshal the results
  // to the AccessorResult object, which Selenium Core interacts with.
  var terminationCondition = /** @this {AccessorResult} */function() {
    if (isDone) {
      this.result = result;
    }
    return isDone;
  };

  // When running in Firefox chrome mode, any DOM elements in the script result
  // will be wrapped with a XPCNativeWrapper or XrayWrapper. We need to
  // intercept the result and make sure it is "unwrapped" before returning to
  // bot.inject.executeAsyncScript.  The function below is in terms of the
  // arguments object only to avoid defining new local values that would be
  // available to the script via closure, but we know the following to be true:
  //   let n = arguments.length, then
  //   arguments[n - 1] -> The "real" async callback. This is provided by the
  //                       bot.inject.executeAsyncScript atom.
  //   arguments[n - 2] -> Our "unwrapper" callback that we give to the user
  //                       script. This is injected via an argument because it
  //                       needs access to variables in this window's scope,
  //                       while the execution context will be
  //                       selenium.browserbot.getCurrentWindow().
  //   arguments[n - 3] -> The user script as a string.
  //   arguments[0..n - 3] -> The user supplier arguments.
  var scriptFn = function() {
    new Function(arguments[arguments.length - 3]).apply(null,
        (function(args) {
          var realCallback = args[args.length - 1];
          var unwrapperCallback = args[args.length - 2];
          Array.prototype.splice.apply(args, [args.length - 3, 3]);
          args.push(function(result) {
            unwrapperCallback(result, realCallback);
          });
          return args;
        })(Array.prototype.slice.apply(arguments, [0])));
  };

  var args = core.inject.removeElementIdPrefix_(json['args']);
  args.push(json['script'], function(scriptResult, realCallback) {
    // bot.inject.executeAsyncScript creates the realCallback, so we capture
    // it through arguments magic in our scriptFn wrapper above. In here, we
    // unwrap any XPCNativeWrappers in the scriptResult, then hand it over to
    // realCallback. This must all be done in this script so the unwrapped
    // result stays in the same context as realCallback.
    scriptResult = core.inject.unwrapResultValue_(scriptResult);
    realCallback(scriptResult);
  });

  bot.inject.executeAsyncScript(scriptFn, args,
      json['timeout'],
      function(value) {
        isDone = true;
        result = core.inject.addElementIdPrefix_(value);
        result = goog.json.serialize(result);
      }, false, selenium.browserbot.getCurrentWindow());

  // Since this function is invoked via getEval(), we need to ensure the
  // returned result, which is wrapped in an |AccessorResult|, has the expected
  // fields.  selenium-executionloop will detect the terminationCondition and
  // enter a loop polling for script to terminate and its result.
  return {'terminationCondition': terminationCondition};
};


/**
 * @param {*} value The value to unwrap.
 * @return {*} The unwrapped value.
 * @private
 */
core.inject.unwrapResultValue_ = function(value) {
  switch (goog.typeOf(value)) {
    case 'array':
      return goog.array.map(value, core.inject.unwrapResultValue_);
    case 'object':
      if (bot.dom.isElement(value)) {
        return core.firefox.unwrap(value);
      }
      return goog.object.map(value, core.inject.unwrapResultValue_);
    default:
      return core.firefox.unwrap(value);
  }
};


/**
 * Prefix applied to cached element IDs so that they may be used with normal
 * Selenium commands.
 * @type {string}
 * @const
 */
core.inject.ELEMENT_ID_PREFIX = 'stored=';


/**
 * @param {*} value The value to scrub.
 * @return {*} The scrubbed value.
 * @private
 */
core.inject.removeElementIdPrefix_ = function(value) {
  if (goog.isArray(value)) {
    return goog.array.map((/**@type {goog.array.ArrayLike}*/value),
        core.inject.removeElementIdPrefix_ );
  } else if (value && goog.isObject(value) && !goog.isFunction(value)) {
    if (goog.object.containsKey(value, bot.inject.ELEMENT_KEY)) {
      var id = value[bot.inject.ELEMENT_KEY];
      if (id.substring(0, core.inject.ELEMENT_ID_PREFIX.length) ===
          core.inject.ELEMENT_ID_PREFIX) {
        value[bot.inject.ELEMENT_KEY] =
            id.substring(core.inject.ELEMENT_ID_PREFIX.length);
        return value;
      }
      return goog.object.map(value, core.inject.removeElementIdPrefix_);
    }
  }
  return value;
};


/**
 * @param {*} value The value to update.
 * @return {*} The updated value.
 * @private
 */
core.inject.addElementIdPrefix_ = function(value) {
  if (goog.isArray(value)) {
    return goog.array.map((/**@type {goog.array.ArrayLike}*/value),
        core.inject.addElementIdPrefix_ );
  } else if (value && goog.isObject(value) && !goog.isFunction(value)) {
    if (goog.object.containsKey(value, bot.inject.ELEMENT_KEY)) {
      value[bot.inject.ELEMENT_KEY] =
          core.inject.ELEMENT_ID_PREFIX + value[bot.inject.ELEMENT_KEY];
      return value;
    }
    return goog.object.map(value, core.inject.addElementIdPrefix_);
  }
  return value;
};
