/*
 * Prepare
 */

// параметры функций
parseUri.options = {
    strictMode: false,
    key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],
    q:   {
        name:   "queryKey",
        parser: /(?:^|&)([^&=]*)=?([^&]*)/g
    },
    parser: {
        strict: /^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,
        loose:  /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/
    }
};

// ошибки
var msgs = new messages();

// создаем лоадер
var l = new loader();

// создаем плагин
var pl = new plugin();

/*
 * Обрабатываем загрузку страницы
 */

// создём объект хеша
var h = new hash();

$(document).ready(function(){

});

/*
 * Functions
 */

function implode(glue, pieces) {
    return ((pieces instanceof Array) ? pieces.join (glue) : pieces);
}

function in_array(needle, haystack, strict) {	// Checks if a value exists in an array
    // 
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)

    var found = false, key, strict = !!strict;

    for (key in haystack) {
        if ((strict && haystack[key] === needle) || (!strict && haystack[key] == needle)) {
            found = true;
            break;
        }
    }

    return found;
}

function intval( mixed_var, base ) {	// Get the integer value of a variable
    //
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)

    var tmp;

    if( typeof( mixed_var ) == 'string' ){
        tmp = parseInt(mixed_var);
        if(isNaN(tmp)){
            return 0;
        } else {
            return tmp.toString(base || 10);
        }
    } else if( typeof( mixed_var ) == 'number' ){
        return Math.floor(mixed_var);
    } else{
        return 0;
    }
}

// предзагрузка изображений
function preload() {
    for(var i = 0; i<arguments.length; i++)
        $("<img>").attr("src", arguments[i]);
};

// парсилка урлов
function parseUri(str) {

    var	o   = parseUri.options,
    m   = o.parser[o.strictMode ? "strict" : "loose"].exec(str),
    uri = {},
    i   = 14;

    while (i--) uri[o.key[i]] = m[i] || "";

    uri[o.q.name] = {};
    uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {
        if ($1) uri[o.q.name][$1] = $2;
    });

    return uri;

};

function split( val ) {
    return val.split( /,\s*/ );
}
function extractLast( term ) {
    return split( term ).pop();
}

function function_exists(function_name) {
    // 
    // +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Steve Clay
    // +   improved by: Legaev Andrey


    if (typeof function_name == 'string'){
        return (typeof window[function_name] == 'function');
    } else{
        return (function_name instanceof Function);
    }
}

/**
 * Активируем загрузчик файлов
 *
 * @param string form айди формы
 * @param string input айди файл-инпута
 * @param array params параметры для запроса (см. основную функцию request)
 * @param array opts опции запроса (см. основную функцию request)
 * @param array nparams расширение параметров params
 * @param array no расширение стандартных опций ЗАГРУЗЧИКА
 */
function uploader(form, input, params, opts, nparams, no) {

    // обновляем параметры для колбэка
    $.extend(params, nparams);
    // парсим акшн формы
    var uri = parseUri($("#" + form).attr("action"));
    var d = uri.queryKey;
    // добавляем куки авторизации, а то они через флеш не проходят
    d['cms_user_id'] = $.cookie("cms_user_id");
    d['cms_user_hash'] = $.cookie("cms_user_hash");
    d['ajax'] = true;
    // добавим в гет скрытые инпаты
    $("#" + form + " input[type=hidden]").each(function(){
        d[$(this).attr("name")] = $(this).val();
    });
    // запоминаем параметры
    var o = {
        'uploader': "/" + globals['js'] + "uploadify.swf",
        'script': "/index.php",
        'cancelImg': "/" + globals['skin'] + "i/icons/cancel.png",
        'fileDataName': "file",
        'auto': true,
        'onComplete': function(event, queueID, fileObj, response, data) {
            // если нам вернулся не json
            if(response[0] != "{")
                alert("Invalid data format:\n" + response);
            else {
                //alert(response);
                var d = eval( '(' + response + ')' );
                decide(d, params, opts);
            }
        },
        'onError': function(a, b, c, d) {
            if (d.status == 404)
                alert('Could not find upload script. Use a path relative to: ' + '<?= getcwd() ?>');
            else if (d.type === "HTTP")
                alert('error ' + d.type + ": " + d.info);
            else if (d.type === "File Size")
                alert(c.name + ' ' + d.type + ' Limit: ' + Math.round(d.sizeLimit / 1024) + 'KB');
            else
                alert('error ' + d.type + ": " + d.info);
        },
        'scriptData': d,
        'method': "GET"
    };
    // расширяем опции загрузчика
    $.extend(o, no);
    // настроили загрузчик
    $("#" + input).uploadify(o);
    $("#" + form + " .uploader .input.submit").hide();

}

// плагин
function plugin() {

    this.data = null;
    this.params = null;
    this.opts = null;

    this.cfg = function(data, params, opts) {
        this.data = data;
        this.params = params;
        this.opts = opts;
    }

    this.appoint = function(result, action, func) {
        // текст ошибки
        var fail = "Action overwrite error for result `" + result + "` and action `" + action + "`.";
        // результат
        switch(result) {
            // успех
            case 'scs':
                this[action] = func;
                break;
            // ошибка
            case 'msg':
                this["msg_" + action] = func;
                break;
            // не правильно передан результат
            default:
                alert(fail);
                break;
        }
    }

    this.scs = function() {
        // запомнили действие
        var act = this[this.params['action']];
        // если нет обработчика
        if(!act) {
            // проверяем редирект
            if(this.data.redirect)
                window.location = this.data.redirect;
            // по дефолту просматриваем
            else
                act = this["view"];
        }
        // вызвали
        act(this.data, this.params, this.opts);
    }

    this.msg = function() {
        // покажем сообщение
        msgs.show(this.data);
        // если акш не передан
        if(!this.params['action'])
            // это по дефолту просмотр
            this.params['action'] = "view";
        // запомнили действие
        var act = this["msg_" + this.params['action']];
        // если есть обработчик
        if(act)
            // вызваем
            act(this.data, this.params, this.opts);
    }

}

/*
 * Ajax
 */

// обработчик
function decide(data, params, opts) {

    // конфигурируем плагин
    pl.cfg(data, params, opts);
    // запоминаем объект нужного нам класса
    var clss = window["pl_" + opts['plugin']];
    if(clss == undefined)
        alert("Can`t find javascript class of plugin `" + opts['plugin'] + "`.");
    else {
        // есть ошибки - запустим обработчик ошибок, иначе - обработчик успеха
        data.msgs == undefined ? clss.scs() : clss.msg();
    }

}

// обработчик формы
function fpage(opts, params) {

    // парсим акшн формы
    var uri = parseUri($("#" + opts.form).attr("action"));

    // сабмит кнопку делаем неактивной
    $("#" + opts.form + " input[type=submit]").attr("disabled", true);
    // оформляем колбэк
    opts.callback = function() {
        // в колбэк - активируем обратно
        $("#" + opts.form + " input[type=submit]").removeAttr("disabled");
    }
    // блокируем обновление хеша
    opts.hashLock = true;

    // запрос по урлу
    return upage(uri, opts, params);

}

// обработчик клика по линке
function lpage(opts, params) {

    // если передан хреф
    var url = "";
    opts.href ? url = opts.href : url = $("#" + opts.link).attr("href");

    // парсим урл ссылки
    var uri = parseUri(url);
    // запрос по урлу
    return upage(uri, opts, params);

}

// обработчик запроса по урлу
function upage(uri, opts, params) {

    // запоминаем страницу и удаляем из списка
    var page = uri.queryKey['page'];
    delete uri.queryKey['page'];

    // если нет доп. пареметров
    if(!params)
        // запишем пустую строку
        params = null;
    else {
        // иначе нужно заменить или добавить параметры
        for(var key in params)
            uri.queryKey[key] = params[key];
    }
    // возвращаем резалт запроса
    return request(page, uri.queryKey, opts);

}

/**
 * Аналог print_r php
 */
function print_r(arr, level) {
    var print_red_text = "";
    if(!level) level = 0;
    var level_padding = "";
    for(var j=0; j<level+1; j++) level_padding += "    ";
    if(typeof(arr) == 'object') {
        for(var item in arr) {
            var value = arr[item];
            if(typeof(value) == 'object') {
                print_red_text += level_padding + "'" + item + "' :\n";
                print_red_text += print_r(value,level+1);
            } 
            else 
                print_red_text += level_padding + "'" + item + "' => \"" + value + "\"\n";
        }
    } 

    else  print_red_text = "===>"+arr+"<===("+typeof(arr)+")";
    return print_red_text;
}

/**
 * Обработчик ajax-запросов
 *
 * @param string page параметр GET`а page
 * @param array params дополнительные параметры GET`а
 * @param array opts дополнительные параметры запроса
 * string form айди формы откуда еще собрать данные
 * string loader айди лоадера
 * bool hashLock для блокировки обновления хэша
 * function callback колбэк после выполения запроса
 * string plugin плагин, который обрабатывает результат выполения
 */
function request(page, params, opts) {

    // пост данные
    var post = null;
    // если нет опций
    if(!opts)
        // запишем пустую строку
        opts = null;
    else {
        // если выбран кастомный лоадер
        if(opts.loader) {
            l.id = opts.loader;
        }
        // если еще нужно собрать данные с формы
        if(opts.form)
            post = $("#" + opts.form).serialize();
    }

    // показываем лоадер
    l.show();

    // очищаем список ошибок
    msgs.clear();

    var get = ""; // GET данные

    if(params) // если есть параметры - добавляем в GET
        for(var key in params)
            get += key + "=" + params[key] + "&";

    // делаем ajax-запрос
    $.ajax({
        type: "POST",
        url: "/?page=" + page + "&" + get + "ajax", // в конец урла дописываем ajax, чтобы скрипт знал, что он вызван аяксом
        data: post,
        // все хорошо
        success: function(html) {
            // если нам вернулся не json
            if(html[0] != "{" && !($.browser.msie)) { // ебыный ie, чтоп ты сдох, сука!
                // прячем лоадер
                l.hide();
                // показываем
                alert("Invalid data format:\n" + html);
            }
            else {
                //alert(html);
                var data = eval( '(' + html + ')' );
                // прячем лоадер
                l.hide();
                // решаем, чо делать дальше
                decide(data, params, opts);
                // обновляем хеш, если не закрыта эта функция
                if(!opts.hashLock)
                    h.upd({
                        "url": get + "page=" + page,
                        "plugin": opts['plugin']
                    });
            }
            // вызываем колбэк
            if(typeof(opts.callback) == "function") {
                opts.callback();
            }
        },
        // произошла ошибка
        error: function(obj) {
            // прячем лоадер
            l.hide();
            // показываем
            alert("Server error: " + obj.status);
            // вызываем колбэк
            if(typeof(opts.callback) == "function")
                opts.callback();
        }
    });

    return false;

}
