/*
 * 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 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;

};

/**
 * Активируем загрузчик файлов
 *
 * @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;
    // запоминаем параметры
    var o = {
        'uploader': globals['js'] + "uploadify.swf",
        'script': "index.php",
        'cancelImg': globals['skin'] + "i/icons/icon-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);
            }
        },
        '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", "disabled");
    // оформляем колбэк
    opts.callback = function() {
        // в колбэк - активируем обратно
        $("#" + opts.form + " input[type=submit]").attr("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);

}

// обработчик ajax
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: "index.php?page=" + page + "&" + get + "ajax", // в конец урла дописываем ajax, чтобы скрипт знал, что он вызван аяксом
		data: post,
        // все хорошо
		success: function(html) {
            // если нам вернулся не json
            if(html[0] != "{") {
                // прячем лоадер
                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']
                    });
            }
            // вызываем колбэк
            opts.callback();
		},
        // произошла ошибка
		error: function(obj) {
            // прячем лоадер
			l.hide();
            // показываем
			alert("Server error: " + obj.status);
            // вызываем колбэк
            opts.callback();
		}
	});

	return false;

}
