text: define([], function() {
    //'use strict'; //TODO: add back in as soon as our plugins are fixed
  
    var hasOwnProperty = {}.hasOwnProperty,
        indexOf = [].indexOf,
        noop = function() {},
        push = [].push,
        slice = [].slice,
        toString = {}.toString,
        PI = Math.PI;
  
    /**
     *
     * This module contains generic utility functions which are used heavily
     * internally.
     *
     * @exports tools
     */
    var tools = {
  
      /**
       * Returns the base url directory for a given document.
       *
       * This value can be used to create URLs relative to a document. It is
       * guaranteed to have a trailing slash.
       *
       * @param {HTMLDocument} document
       * @returns {string}
       */
      baseUri: function(document) {
        var undefined, baseUri = document.baseURI;
        if (baseUri !== undefined) {
          // remove non-dir components at end, ensure trailing slash;
          return baseUri.replace(/[/]+[^/]*$/, '/');
        } else {
          var a = document.createElement('a');
          a.href = '.';
          return a.href;
        }
      },
  
      /**
       * Creates a new object with the given [[Prototype]].
       *
       * @param {Object} prototype The [[Prototype]].
       * @returns {Object} The new object.
       */
      beget: function(prototype) {
        noop.prototype = prototype;
        return new noop;
      },
  
      /**
       * Creates a property descriptor for an accessor property.
       *
       * @param {Function} get The getter function
       * @param {Function} set The setter function
       * @param {boolean} [enumerable] Whether the property should be enumerable
       * @param {boolean} [configurable] Whether the property should
       *  be configurable
       * @returns {Object} A property descriptor suitable for Object.create(),
       *  Object.defineProperty() and Object.defineProperties().
       */
      descriptorAccessor: function(get, set, enumerable, configurable) {
        return {
          get: get,
          set: set,
          enumerable: !!enumerable,
          configurable: !!configurable
        };
      },
  
      /**
       * Creates a property descriptor for a data property.
       *
       * @param {any} value The initial value
       * @param {boolean} [writable] Whether the property should be writable
       * @param {boolean} [enumerable] Whether the property should be enumerable
       * @param {boolean} [configurable] Whether the property should
       *  be configurable
       * @returns {Object} A property descriptor suitable for Object.create(),
       *  Object.defineProperty() and Object.defineProperties().
       */
      descriptorData: function(value, writable, enumerable, configurable) {
        return {
          value: value,
          writable: !!writable,
          enumerable: !!enumerable,
          configurable: !!configurable
        };
      },
  
      /**
       * A generic `Array#forEach` like method.
       * Callbacks may terminate the loop by explicitly returning `false`.
       *
       * @param {Array} array The array to iterate over.
       * @param {Function} callback The function called per iteration.
       * @param {Object} thisArg The `this` binding for the callback function.
       * @returns {Array} Returns the array iterated over.
       */
      forEach: function(array, callback, thisArg) {
        var index,
            length = array.length;
  
        // optimize for the common case of not providing a `thisArg`
        thisArg && (callback = tools.hitch(thisArg, callback));
        for (index = 0; index < length; index += 1) {
          if (callback(array[index], index, array) === false) {
            break;
          }
        }
        return array;
      },
  
      /**
       * Iterates over an object's own properties, executing the `callback` for each.
       * Callbacks may terminate the loop by explicitly returning `false`.
       *
       * @param {Object} object The object to iterate over.
       * @param {Function} callback The function executed per own property.
       * @param {Object} thisArg The `this` binding for the callback function.
       * @returns {Object} Returns the object iterated over.
       */
      forOwn: function(object, callback, thisArg) {
        // optimize for the common case of not providing a `thisArg`
        thisArg && (callback = tools.hitch(thisArg, callback));
        for (var key in object) {
          if (hasOwnProperty.call(object, key) &&
              callback(object[key], key, object) === false) {
            break;
          }
        }
        return object;
      },
  
      /**
       * Creates a simple getter.
       *
       * The function returned will return the property specified from the
       * respective context (`this`) on invokation.
       *
       * @param {string} propertyName The name of the property to look up.
       * @returns {Function}
       */
      getter: function(propertyName) {
        return function() {
          return this[propertyName];
        };
      },
  
      /**
       * Returns a function that will only ever execute with a specified `this` binding.
       *
       * @param {Object} thisArg The `this` binding for the `fn` function.
       *  If `fn` is a string, `thisArg` is also the object containing `fn`.
       * @param {Function|string} A function to be bound to `thisArg`, or the name
       *  of the method in `thisArg` to be bound.
       * @param [fixedArgs...] Any number of parameters. Will be passed to the
       *  bound function before any other parameters.
       * @returns {Function} The bound function.
       */
      hitch: function(thisArg, fn, fixedArgs) {
        if (arguments.length > 2) {
          fixedArgs = slice.call(arguments, 2);
          var fixedLength = fixedArgs.length;
        }
        if (typeof fn == 'string') {
          fn = thisArg[fn];
        }
        return fixedArgs ?
          function() {
            // resetting `fixArgs` length + push is faster than concat + slice
            fixedArgs.length = fixedLength;
            push.apply(fixedArgs, arguments);
            return fn.apply(thisArg, fixedArgs);
          } :
          function() {
            return fn.apply(thisArg, arguments);
          };
      },
  
      /**
       * Performs a strict equality search for the given `value` and returns the
       * index it is found at else `-1`.
       *
       * @param {Array} array The array to iterate over.
       * @param {any} value The value to search for.
       * @param {number} [fromIndex=0] The index to start searching from.
       * @returns {number} The index of the matched value or `-1`.
       */
      indexOf: function(array, value, fromIndex) {
        return indexOf.call(array, value, fromIndex);
      },
  
      /**
       * Checks if a value has an internal `[[Class]]` of Array.
       *
       * @function
       * @param {any} value The value to check.
       * @returns {boolean} Returns `true` if the value has an internal [[Class]]
       *  of Array, else `false`.
       */
      isArray: Array.isArray || function(value) {
        // http://es5.github.com/#x15.4.3.2
        return toString.call(value) == '[object Array]';
      },
  
      /**
       * Returns an array of all own enumerable property names.
       *
       * @function
       * @param {Object} object The object to iterate over.
       * @returns {Array} An array of property names.
       */
      keys: Object.keys || function(object) {
        // http://es5.github.com/#x15.2.3.14
        if (object !== Object(object)) {
          throw TypeError();
        }
        var result = [];
        for (var key in object) {
          if (hasOwnProperty.call(object, key)) {
            result.push(key);
          }
        }
        return result;
      },
  
      /**
       * A generic `Array#map` like method.
       *
       * @param {Array} array The array to iterate over.
       * @param {Function} callback The function called per iteration.
       * @param {Object} thisArg The `this` binding for the callback function.
       * @returns {Array} A new array of values returned by the callback.
       */
      map: function(array, callback, thisArg) {
        var index,
            length = array.length,
            result = Array(length);
  
        // optimize for the common case of not providing a `thisArg`
        thisArg && (callback = tools.hitch(thisArg, callback));
        for (index = 0; index < length; index += 1) {
          result[index] = callback(array[index], index, array);
        }
        return result;
      },
  
      /**
       * Copies all enumerable properties from source object(s) to the destination object.
       * Multiple source objects are supported.
       *
       * @param {Object} destination The object to copy properties to.
       * @param {Object} [source, ..] The object(s) to copy properties from.
       * @returns {Object} The destination object.
       */
      mixin: function(destination, source) {
        var index,
            key,
            length = arguments.length;
  
        for (index = 1; index < length; index += 1) {
          source = arguments[index] || {};
          for (key in source) {
            destination[key] = source[key];
          }
        }
        return destination;
      },
  
      /**
       * Gets absolute offset of the given DOM element.
       *
       * @param {Element} element The DOM element.
       * @returns {Object} An object with the absolute offset left and top values.
       */
      offset: function(element) {
        // TODO: Add corrections for client left/top and scroll offsets
        var left = 0,
            top = 0,
            offsetParent = element;
  
        do {
          left += offsetParent.offsetLeft;
          top += offsetParent.offsetTop;
        } while (offsetParent = offsetParent.offsetParent);
  
        return {
          left: left,
          top: top
        };
      },
  
      /**
       * A generic `Array#reduce` like method.
       *
       * @param {Array} array The array to iterate over.
       * @param {Function} callback The function called per iteration.
       * @param {any} accumulator Initial value of the accumulator.
       * @returns {any} The accumulator.
       */
      reduce: function(array, callback, accumulator) {
        var noaccum = arguments.length < 3;
  
        var index,
            length = array.length;
  
        if (noaccum) {
          accumulator = array[0];
        }
  
        for (index = noaccum ? 1 : 0; index < length; index += 1) {
          accumulator = callback(accumulator, array[index], index, array);
        }
        return accumulator;
      },
  
      /**
       * Removes all occurrences of a value within an array.
       *
       * Can also be used to remove gaps from an array.
       *
       * @param {Array} array The array to remove values from
       * @param [value=undefined] The value to remove from the array
       * @returns {Array} The array passed in.
       */
      removeValueFromArray: function(array, value) {
        var current, numRemoved = 0;
        for (var i = 0, length = array.length; i < length; i += 1) {
          current = array[i];
          if (current === value) {
            numRemoved += 1;
          } else if (numRemoved) {
            array[i - numRemoved] = current;
          }
        }
  
        array.length -= numRemoved;
  
        return array;
      },
  
      /**
       * Parse a given unit string into the amount and unit
       *
       * @param {any} any Anything that can be converted to a string. E.g. '7deg', ['50%']
       * @returns {string} unit
       */
      extractUnit: function (any) {
        // make sure it's a string and remove trailing whitespace
        var unit = String(any).replace(/\s+$/, '');
        // returns extracted unit or empty string
        return unit.match(/[a-z%]*$/i)[0];
      },
  
      /**
       * Parses the angle string to radians
       * https://developer.mozilla.org/en-US/docs/CSS/angle
       *
       * @param {number|string} angle The angle/unit string
       * @returns {number} The angle in radians
       */
      parseAngle: function(angle) {
        var radians,
            unit = tools.extractUnit(angle),
            amount = parseFloat(angle);
  
        switch (unit) {
          case '': // default
          case 'rad':
            radians = amount; break;
          case 'deg':
            radians = amount * PI / 180; break;
          case 'grad':
            radians = amount * PI / 200; break;
          case 'turn':
            radians = amount * 2 * PI; break;
        }
  
        return radians;
      }
    };
  
    return tools;
  });
  