/**
 * Ytils JS Framework
 * type
 *
 * Ytils WebToolBox.
 *
 * Copyright (c) 2011 Kim Schneider, SIT - Schneider Internet Technologies.
 * The Ytils framework is a collection of PHP- and JavaScript utility- and widget-classes written by Kim Schneider.
 *
 * The Ytils WebToolBox is published under the GPL v3-licence. See LICENCE.txt for the licence-text.
 * The official source of the Ytils project is http://www.ytils.com.
 * The official website of SIT - Schneider Internet Technologies is http://www.schneidersit.de.
 *
 * Kiel, Germany, 2011-08-10.
 *
 * @category  YTILS
 * @package   util.js.ytils.com
 * @copyright Copyright (c) 2010 Schneider IT-Services (http://www.schneider.ws)
 * @author    Kim Schneider
 * @license   http://ytils.schneider.ws/licence/
 * @version   1.2.1.1
 */

// JSLint configuration:
/*global YTILS */
/*jslint browser: true */
/*jslint strict: true */
(function(){

"use strict";

if (typeof YTILS.util === "undefined" || !YTILS.util)
{
  YTILS.util = {};
}

YTILS.util.type =
{
  /**
   * Checks if given param is a string.
   *
   * @param mixed o The variable to check.
   * @return Boolean
   */
  isString: function(o)
  {
    return typeof o === 'string';
  },
  
  /**
   * Checks if given param is an empty string.
   *
   * @param mixed o The variable to check.
   * @return Boolean
   */
  isEmptyString: function(o)
  {
    return YTILS.util.type.isString(o) && o === ''; 
  },
  
  /**
   * Checks if given param is an empty string or a string that contains only blanks.
   *
   * @param mixed o The variable to check.
   * @return Boolean
   */
  isEmptyStringTrim: function(o)
  {
    var
    s = YTILS.util.string,
    type = YTILS.util.type;

    if (type.isString(o))
    {
      o = s.trim(o);
      return type.isEmptyString(o);
    }
    
    return false;
  },

  /**
   * Checks if given param is a boolean.
   *
   * @param mixed elem The variable to check.
   * @return Boolean
   */
  isBoolean: function(o)
  {
    return typeof o === 'boolean';
  },

  /**
   * @alias isBoolean
   */
  isBool: function(o)
  {
    return YTILS.util.type.isBoolean(o);
  },

  /**
   * Checks if given param is a number.
   *
   * @param mixed elem The variable to check.
   * @param Boolean checkFinite optional. Add finite-check for validation. Defaults to false. 
   * @return Boolean
   */
  isNumber: function(o)
  {
    var theArgs = arguments;

    if (theArgs.length === 1)
    {
      return typeof o === 'number';
    }

    if (theArgs.length === 2 && theArgs[1])
    {
      return YTILS.util.type.isNumber(o) && isFinite(o);
    }
    else
    {
      return YTILS.util.type.isNumber(o);
    }
  },

  /**
   * Just a passthrough for the javascripts core function.
   * This is for cosmetic looking source only.
   */
  isFinite: function(o)
  {
    return isFinite(o);
  },
  
  /**
   * Checks if given param is not finite.
   *
   * @param Number o The variable to check.
   * @return Boolean
   */
  isInfinite: function(o)
  {
    return !isFinite(o);
  },

  /**
   * Checks if given param is an integer value. This accepts
   * also string values representing an integer.
   *
   * @param mixed elem The variable to check.
   * @param bool (optional) Accept empty as valid integer, defaults to true.
   * @return Boolean
   */
  isInt: function(o)
  {
    var theArgs = arguments,
        i,
        cAt,
        dotCount;

    o = o.toString();
    dotCount = 0;

    if (YTILS.util.type.isEmpty(o) && (theArgs.length === 1 || !theArgs[1]))
    {
      return false;
    }

    for (i = 0; i < o.length; i++)
    {
      cAt = o.charAt(i);
      if (!(cAt === '0' ||
            cAt === '1' ||
            cAt === '2' ||
            cAt === '3' ||
            cAt === '4' ||
            cAt === '5' ||
            cAt === '6' ||
            cAt === '7' ||
            cAt === '8' ||
            cAt === '9'))
      {
        return false;
      }
    }

    return true;
  },

  /**
   * Checks if given param is an integer type. 
   *
   * @param mixed elem The variable to check.
   * @return Boolean
   */
  isIntStrict: function(o)
  {
    if (typeof o !== 'number') 
    {
      return false;
    }

    if (parseFloat(o) !== parseInt(o, 10)) 
    {
      return false;
    }
    
    return true;
  },

  /**
   * @alias isIntStrict
   */
  isIntegerStrict: function(o)
  {
    return YTILS.util.type.isIntStrict(o);
  },
  
  /**
   * @alias isInt
   */
  isInteger: function(o)
  {
    return YTILS.util.type.isInt(o);
  },

  /**
   * Checks if given param is a double. This accepts also strings representing a double value.
   * Note: If one param is passed, this method is equal to isNumber(). 
   *
   * @param mixed elem The variable to check.
   * @param Boolean emptyAllowed optional. Allows empty values to pass the text.
   * @return Boolean
   */
  isDouble: function(o)
  {
    var
    theArgs = arguments,
    i,
    cAt,
    dotCount;

    o = o.toString();
    dotCount = 0;

    if (YTILS.util.type.isEmpty(o) && !theArgs[1])
    {
      return false;
    }

    if (o.charAt(o.length - 1) === ".")
    {
      return false;
    }

    if (o.charAt(0) === ".")
    {
      return false;
    }

    for (i = 0; i < o.length; i++)
    {
      cAt = o.charAt(i);
      if (!(cAt === "0" ||
            cAt === "1" ||
            cAt === "2" ||
            cAt === "3" ||
            cAt === "4" ||
            cAt === "5" ||
            cAt === "6" ||
            cAt === "7" ||
            cAt === "8" ||
            cAt === "9" ||
            cAt === "."))
      {
        return false;
      }

      if (cAt === ".")
      {
        dotCount++;
      }
    }

    if (dotCount > 1)
    {
      return false;
    }

    return true;
  },

  /**
   * Checks if given param is a float.
   * Alias for isDouble.
   */
  isFloat: function(o)
  {
    return YTILS.util.type.isDouble(o);
  },

  /**
   * Checks if given param is a function.
   *
   * @param mixed elem The variable to check.
   * @return Boolean
   */
  isFunction: function(o)
  {
    return typeof o === "function";
  },

  /**
   * Checks if given param is undefined.
   *
   * @param mixed elem The variable to check.
   * @return Boolean
   */
  isUndefined: function(o)
  {
    return typeof o === "undefined";
  },

  /**
   * Checks if given param is null.
   *
   * @param mixed elem The variable to check.
   * @return Boolean
   */
  isNull: function(o)
  {
    return o === null;
  },

  /**
   * Checks if given param is null or undefined.
   *
   * @param mixed elem The variable to check.
   * @return Boolean
   */  
  isNullOrUndefined: function(o)
  {
    var t = YTILS.util.type;
    return t.isNull(o) || t.isUndefined(o);
  },

  /**
   * Checks if given param is a float.
   *
   * Alias for isNullOrUndefined.
   */
  isNothing: function(o)
  {
    return YTILS.util.type.isNullOrUndefined(o);
  },
  
  /**
   * Checks if given param is null or undefined or an empty string.
   *
   * @param mixed elem The variable to check.
   * @param Boolean trim optional. Trim the elem param before the check.
   * @return Boolean
   */  
  isEmpty: function(o)
  {
    var
    theArgs = arguments,
    s = YTILS.util.string,
    t = YTILS.util.type;
    
    if (t.isNullOrUndefined(o))
    {
      return true;
    }
    
    if (t.isString(o) && theArgs.length === 2 && theArgs[1])
    {
      o = o.replace(/\s+$/, "").replace(/^\s+/, "");
    }

    o = o.toString();
    o = s.trim(o);

    return o === "";
  },

  /**
   * Checks if given param is an array.
   *
   * @param mixed o The object to check.
   * @return Boolean
   */
  isArray: function(o)
  {
    return typeof o === "object" &&
           typeof o.length === "number" &&
           typeof o.splice === "function";
  },

  /**
   * Checks if given param is an object or a function.
   *
   * @param mixed o The object to check.
   * @return Boolean
   */
  isObject: function(o)
  {
    return typeof o === "object";
  },

  /**
   * Checks if given param is an object or a function.
   *
   * @param mixed o The object to check.
   * @return Boolean
   */
  isObjectOrFunction: function(o)
  {
    return typeof o === "object" || typeof o === "function";
  },
  
  /**
   * Checks if given param is a hex char.
   *
   * @param mixed o The char to check.
   * @return Boolean 
   */
  isHexChar: function(o)
  {
    o = o.toString().toLowerCase();
    return (o === '0' ||
            o === '1' ||
            o === '2' ||
            o === '3' ||
            o === '4' ||
            o === '5' ||
            o === '6' ||
            o === '7' ||
            o === '8' ||
            o === '9' ||
            o === 'a' ||
            o === 'b' ||
            o === 'c' ||
            o === 'd' ||
            o === 'e' ||
            o === 'f');   
  }
};

}());
