/** var $type = pulp.type; */
pulp.Modules.type = '$type';

/*
 * based on Prototype 1.6.1 rc3
 * 
 */(function() {

  var $p = pulp.base;
  var toStringTypes = 'Array Function Boolean String Number Date RegExp Object';
  var knownTypes = ('Element Document Undefined Null ' + toStringTypes).split(' ');

  /**
   * @name pulp.type
   * @class
   * @param {Object} object  The object to test
   * @return {String} The name of the type (Element|Array|Function|Boolean|String|Number|Undefined) etc.
   */
  var $t = pulp.type = function(o) {
    var i = 0, m;
    while ((m = knownTypes[i++])) {
      if ($t['is' + m](o)) {
        return m.toLowerCase();
      }
    }
    return $p.objectType(o);
  };
  
  $p.each(toStringTypes, function(objType) {
    $t['is' + objType] = function(o) {
      return $p.objectType(o) == objType;
    };
  }); 
  
  $p.extend($t, /** @lends pulp.type */{
 		isWindow: function(o) {
      if (o === window || o === top) {
        return true;
      }
      var i = 0, frame;
      while ((frame = window.frames[i++])) {
        if (frame.window === o) {
          return true;
        }
      }
      return false;
      //return (/window$|^global$/i).test($p.objectType(o)); 	
    },
    
    isElement: function(o) {
      return !!(o && o.nodeType == 1);
    },
    
    isDocument: function(o) {
      return $p.objectType(o) == 'HTMLDocument';
    },

    isUndefined: function(o) {
      return typeof o == 'undefined';
    },
    
    isNull: function(o) {
      return o === null;
    },
    
    isStringOrNumber: function(o) {
      return $t.isString(o) || $t.isNumber(o);
    },
    
    isInteger: function(o) {
      return $t.isNumber(o) && String(o).indexOf('.') == -1;
    },
    
    isDecimal: function(o) {
      return $t.isNumber(o) && String(o).indexOf('.') > -1;
    },
    
    isFinite: function(o) {
      return $t.isNumber(o) && !isNaN(o) && o !== Infinity && o !== -Infinity;
    },
    
    isCallable: function(o) {
      return $t.isFunction(o) || $t.isNativeFunction(o);
    },
    
    hasProperties: function(o) {
      if (o) {
        for (var p in o) {
          if (Object.hasOwnProperty(p)) {
            return true;
          }
        }
      }
      return false;			
    },
    
    isNativeFunction: $p.isNative,
    
    isNaN: window.isNaN,
    
    isEmpty: function(o) {
      if ($t.isDocument(o)) {
        return o.getElementsById('body')[0].children.length === 0;
      }
      if ($t.isElement(o)) {
        return o.children.length === 0;
      }			
      switch ($p.objectType(o)) {
        case 'Date':
          return false;
        case 'Function':			
          return (/^\s*function[^\(]*\(\s*\)\s*\{\s*\}*$/).test(o.toString());
        case 'Boolean':
          return o == false;
        case 'Number':
          return o == 0 || isNaN(o);
        case 'RegExp':
          return o.valueOf() == '/(?:)/' || o.valueOf() == '//';
        case 'String':
        case 'Array':
          return o.length === 0;
      }			
      // objects, undefined and null will end up here
      return !$t.hasProperties(o);
    },
    
    isFalsy: function(o) {
      return (o && o.valueOf ? !o.valueOf() : !o);
    },
    
    isTruish: function(o) {
      return (o && o.valueOf ? !!o.valueOf() : !!o);
    }
  });
  
})();