/**
 *$Id: globals.js 81 2008-09-30 13:46:06Z vakparov $
 *
 * global неймспейс
 */
PuskFramework.globals = new function()
{
    var pf = PuskFramework;

    /*
     * Подмена контекста вызова функции
     *
     * @param {Object} obj контекст (обычно this)
     * @return {Function}
     */
    Function.prototype.bind = function(obj)
    {
        var method = this;
        var temp = function()
        {
            return method.apply(obj, arguments);
        };
        return temp;
    };



    /**
     * Сокращенный вариант document.getElementById
     *
     * @param {Object} elementId
     * @return {Object}
     */
    this.$ = function(elementId)
    {
        return pf.elem.get(elementId);
    };

    /**
     * Конструктор элементов HTML
     *
     * @param {Object} tag тэг
     * @param {Object} props свойства элемента
     * @param {Object} cssStyle стиль элемента
     * @return {Object}
     */
    this.$$$ = function(tag, props, cssStyle)
    {
        return pf.elem.construct(tag, props, cssStyle);
    };

    /**
     * Удаление элемента из DOM
     *
     * @param {Object} elem ссылка на элемент
     * @return {Object} возвращает сам элемент
     */
    this.$_ = function(elem)
    {
        return pf.elem.remove(elem);
    };

    /**
     * Возвращает тип объекта
     *
     * @param {Object} obj
     * @return {String}
     */
    this.$type = function(obj)
    {
        if (obj === null) return null;
        if (obj && obj.tagName && !obj.length) 
        {          
          return 'element';
        }
        var type = typeof obj;
        if (type == 'object' && obj.nodeName)
        {
            switch (obj.nodeType)
            {
                case 1:                    
                    return 'element';
                case 3:
                    return (/\S/).test(obj.nodeValue) ? 'textnode' : 'whitespace';
            }
        }
        if (type == 'object' || type == 'function')
        {
            switch (obj.constructor)
            {
                case Array:
                    return 'array';
                case RegExp:
                    return 'regexp';
            }
            if (typeof obj.length == 'number')
            {
                if (obj.item) return 'collection';
            }
        }
        return type;
    };

    /**
     * Возвращает текущее время в формате timestamp или разницу между
     * текущим временем и временем, заданным в качестве аргумента
     *
     * @param {Object} startTime время для сдвига
     * @return {Integer}
     */
    this.$time = function(startTime)
    {
        var now = new Date().getTime();
        return startTime ? now - startTime : now;
    };

    /**
     * Функция предназначена для кроссбраузерной обработки любых событий
     * осуществляет выставление ключевых свойств
     *
     * @param {Object} evt объект типа event
     * @return {Object}
     */
    this.$event = function(evt)
    {
        evt = pf.evt.e(evt);
        if (evt && !evt.target)
        {
            evt.target  = evt.srcElement;

            if (evt.type == 'mouseover')
            {
                evt.relatedTarget = evt.fromElement;
            }
            else if (evt.type == 'mouseout')
            {
                evt.relatedTarget = evt.toElement;
            }
            evt.stopPropagation = function()
            {
                this.cancelBubble = true
            };
            evt.preventDefault = function()
            {
                this.returnValue = false
            };
        }
        return evt;
    };

    /**
     * Аналог empty() в PHP, предназначена для проверки ненулевого значения элемента
     *
     * @param {Object} smth элемент для проверки
     * @return {Bool}
     */
    this.$empty = function(smth)
    {
        switch (pf.$type(smth))
        {
            case 'object':
                for (var i in smth)
                { return false; }
                return true;
            case 'array':
                return smth.length == 0;
            default: return !smth;
        }
    };

    /**
     * Расширяет один объект всеми свойствами другого
     *
     * @param {Object} destination объект получатель
     * @param {Object} source объект донор
     * @return {Object}
     */
    this.$extend = function(destination, source)
    {
        for (var property in source)
            destination[property] = source[property];
        return destination;
    };

    /**
     * Унивесральный выбрасыватель исключений
     * 
     * @param {Object} параметры
     * @return {Object}     
     */                   
    this.$exGen = function(message, exceptionType, filename, line)
    {
      var exception;
      exceptionType = exceptionType || 'error';
      
      switch (exceptionType)
      {
        case 'type': exception = new TypeError(message);break;        
        default: exception = new Error(message);break;
      }
      
      return exception;
    };
    /**
     * Развертывание функций обработчиков, если в качестве обработчика задана не функция, а объект
     *
     * @param {Object} _callback
     * @return {Function}
     */
    pf._expandCallBack = function(_callback)
    {
        switch (true)
        {
            default:
            case (typeof(_callback) == 'function' || !_callback):
                return _callback;
            case (typeof(callback) == 'object'):
            {
                var _scope = _callback.scope || window;
                var _func = _callback.func;
                var _args = _callback.args;
                var _temp = function()
                {
                    if (_args)
                    {
                        for (var i = 0; i < _args.length; i++)
                            arguments.push(_args[i]);
                    }
                    return _func.apply(_scope, arguments);
                };
                return _temp;
            }
        }
    };
};

