// global неймспейс //

/**
 * Сокращенный вариант document.getElementById
 *
 * @param {Object} elementId
 * @return {Object}
 */
function $(elementId)
{
    return (typeof elementId == 'string') ? document.getElementById(elementId) : elementId;
};

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

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

/**
 * Возвращает тип объекта
 *
 * @param {Object} obj
 * @return {String}
 */
function $type(obj)
{
    if (!obj) return false;
    if (obj.tagName) 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}
 */
function $time(startTime)
{
    var now = new Date().getTime();
    return startTime ? now - startTime : now;
};

/**
 * Функция предназначена для кроссбраузерной обработки любых событий
 * осуществляет выставление ключевых свойств
 *
 * @param {Object} evt объект типа event
 * @return {Object}
 */
function $event(evt)
{
    evt = PuskFramework.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}
 */
function $empty(smth)
{
    if (typeof(smth) != 'object') 
    { return !smth; }
    for (var i in smth) 
    { return false; }
    return true;
};

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

// framework config //
var PuskFramework = {
    '_cfg': {
        'namespace': 'pf',
        'extendArray': true,
        'extendString': true,
        'extendDate': true
    }
};

// framework functions //

/** 
 * Развертывание функций обработчиков, если в качестве обработчика задана не функция, а объект
 *
 * @param {Object} _callback
 * @return {Function}
 */
PuskFramework._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;
        }
    }
};

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

/**
 * Возвращает случайное целое число в диапазоне от min до max
 *
 * @param {Object} min минимальное значение
 * @param {Object} max максимальное значение
 * @return {Integer}
 */
Math.rand = function(min, max)
{
    var res = Math.random();
    return (min == undefined || max == undefined) ? res : Math.floor(res * (max - min + 1) + min);
};

/**
 * Преобразует строку в шестнадцатиричном формате в целое число
 *
 * @param {Object} dec
 * @return {Integer}
 */
Math.dec2hex = function(dec)
{
    var hexChars = '0123456789abcdef';
    var a = dec % 16;
    return '' + hexChars.charAt((dec - a) >>> 4) + hexChars.charAt(a);
};
