var dataManager = Class.create();
dataManager.prototype = {
    // Свойства

    method        : 'POST',   // Метод отправки данных.
    backendScript : false,    // Путь к бекенд-скрипту.
    components    : {},       // Компоненты (компоненты формы)
    loadData      : {},       // Данные, загруженные из бекенда. Формат {id: {key:value, key1:value1}}
    errors        : {},       // ошибки, полученные от бэкенда
    mode          : 'a',      // Текущий режим работы датаменеджера
                              // a - добавление данных.
                              // u - обновление (изменение).
                              // f - вызов элемента на редактирование, заполнение формы.
                              // l - загрузка данных из бэкенда
    // Методы

    // конструктор
    initialize: function(params) {
    },

    // добавление в объект компонентов с типом отличным от formComponent
    addComponent: function (component) {
        if (this.components[component.name])
            delete(this.components[component.name]);
        this.components[component.name] = component;
        component.owner = this;
        // выполнить метод addToForm (добавление в форму), если он определен
        if (component.owner && component.addToForm)
            component.addToForm();
    },

    // данные элементов формы (name, value) преобразовать в объект params для Ajax.Request
    getRequestParams: function () {
        var params = {};
        var name = '';
        for (name in this.components) {

            if (this.components[name].type == 'file') {
                params[name] = this.components[name].element;
            } else
                params[name] = this.components[name].value;
        }
        return params;
    },

    // очистка формы от введенных данных, кроме скрытых полей (hidden)
    clearFields: function() {
        var name = '';
        for (name in this.components) {
            var component = this.components[name];
            if (component.type == 'hidden')
                continue;
            component.setValue('');
            component.resetError();
            component.refreshValue();
        }
        this.onClearForm();
    },

    // установить ошибки в компоненты, отобразить
    setErrors: function(errors) {
        var result = false;
        // ошибка не в компонентах, а при выполнении бэкенда
        if (errors.backend_error) {
            alert(errors.backend_error);
            result = true;
        }
        var name = '';
        for (name in this.components) {
            var component = this.components[name];
            if (errors[name]) {
                component.setError(errors[name]);
                result = true;
            }
        }
        return result;
    },

    // отправить данные бекенд-скрипту
    sendData: function (mode, parameters) { // parameters - данные в виде объекта, передаваемые бэкенду
        var that = this;
        if (mode)
            this.mode = mode;
        if (!this.backendScript) {
            alert("Не указан путь к backend-скрипту");
            return;
        }
        // перед отправкой данных выполнить методы submit компонентов,
        // (если они устновлены)
        // если хоть один submit() вернет false, данные не отправлять
        if ((this.mode == 'a') || (this.mode == 'u')) {
            var name = '';
            for (name in this.components) {
                // если у компонента установлен метод submit,
                // выполняющийся перед отправкой формы
                var cmp = this.components[name];
                cmp.refreshValue();
                if (cmp.submit)
                    if (!cmp.submit())
                        return false;
            }
        }
        if (this.mode == 'd') {
            if (!this.onDelete())
                return false;
        }
        this.onSend();
        var cmpParams = this.getRequestParams();
        if (!parameters)
            parameters = {};
        var r = new Ajax.Request(this.backendScript, {
            method: this.method,
            // mode - режим передачи (добавление, редактирование, вызов на редактирование)
            // components - данные из компонентов в формате "имя=>значение"
            // parameters - дополнительные параметры в формате "имя=>значение"
            // в бэкенд поступят в виде массивов $_REQUEST['mode'], $_REQUEST['components'], $_REQUEST['parameters']
            parameters: {mode: this.mode, components: cmpParams, parameters: parameters},
            // в случае ошибки передачи
            //--------------------------
            onFailure: function(tr) {
                that.onFailure();
            },

            //--------------------------
            onSuccess: function(tr) {
                if ($H(tr.responseJS.loadData).size() && (that.mode != 'f'))
                    Object.extend(that.loadData, tr.responseJS.loadData);

                if ($H(tr.responseJS.loadData).size() && (that.mode == 'l'))
                    that.loadData = tr.responseJS.loadData;


                that.fillData = false;
                if ((that.mode == 'f') || (that.mode == 'u') || (that.mode == 'a'))
                    that.fillData = tr.responseJS.loadData;

                if ((tr.responseJS.id) && (that.mode == 'd'))
                   delete that.loadData[tr.responseJS.id];

                that.errors = tr.responseJS.errors;
                if ($H(that.errors).size())
                    that.onSendError();
                else
                    // выполнить в случае успеха, если нет ошибок
                    that.onSendSuccess(mode);

                // устанавливаем значения в компоненты, если таковые имеются

                    $H(tr.responseJS.loadData).each(function(ld) {
                        var cmp = that.components[ld.key];
                        if (cmp && cmp.setValue)
                            cmp.setValue(ld.value);
                    });

                // устанавливаем ошибки, если они есть
                that.setErrors(tr.responseJS.errors);
            }
        });
        return true;
    },

    // выполняется перед передачей данных бэкенду
    onSend: function() {
    },

    // выполняется перед удалением данных
    onDelete: function() {
        return confirm('Удалить?');
    },

    // выполняется, если бэкенд успешно принял данные
    onSendSuccess: function(mode) {
        alert('Данные приняты нормально! Режим: '+mode);
    },

    // бэкенд нашел ошибки в зачениях компонентов
    onSendError: function() {
    },

    // какой-то сбой при передаче данных
    onFailure: function() {
        alert('Ошибка передачи данных');
    },

    // выполниь после очистки формы
    onClearForm: function() {
    }
};
