/*
Редактирование данных в списке
*/


// элемент списка
var listItem = Class.create();
listItem.prototype = {
    initialize: function(params) {
        Object.extend(this, params);
        this.selected = false;
        this.currentTemplate = false;
    },

    // применить шаблон и заполнить элемент списка данными
    write: function(tplName, rewrite) {
        if ((this.currentTemplate == tplName) && (!rewrite))
            return;
        if (!tplName)
            tplName = this.currentTemplate;
        var tplt = "";
        if (this.data.templates) {
            tplt = this.list.itemTemplates[this.data.templates[tplName]];
        } else {
            tplt = this.list.itemTemplates[tplName];
        }
        var tpl = new Template(tplt);
        var html = tpl.evaluate(this.data);
        if (!this.element) {
            new Insertion.Bottom(this.list.listHolder, html);
            this.element = this.list.listHolder.lastChild;

        } else {
            new Insertion.After(this.element, html);
            var element = this.element.nextSibling;
            this.list.listHolder.removeChild(this.element);
            this.element = element;
        }
        $(this.element).show();
        Event.observe(this.element, 'click', this.select.bindAsEventListener(this), false);
        this.currentTemplate = tplName;
    },

    // выбор элемента списка
    select: function(e) {
        this.list.focusList(true);
        var that = this;
        if ((this.currentTemplate == 'edit') || (this.currentTemplate == 'add') || (this.currentTemplate == 'select'))
            return;
        // сначала убрать выбор(выделение) со всех элементов списка
        this.list.unselectAll();
        this.selected = true;
        this.list.selectedItemId = this.id;
        this.write('select');
        if (this.list.onSelectScript) {
            var func = this.list.onSelectScript;
            func = func.replace(/#\{id\}/g, this.id);
            eval(func);
        }
    }
}

// редактируемый список с навигацией
var listEdit = Class.create();
listEdit.prototype = {
    initialize: function(params) {
        var that = this;
        // значения по умолчанию
        this.focusedListClass = "";
        this.itemTemplates ={};
        this.name = 'list';
        this.getParams = {};
        // кол-во строк всего, будет получено при выполнении getList
        this.total = 0;
        this.perPage = 10;
        this.filterText = "";

        Object.extend(this, params);

        // инициализация
        window[this.name] = this;
        this.listItems = {};
        this.selectedItemId = 0;
        this.listHolder = $(this.name);
        this.loadingImg = $(this.name+'Loading');
        this.filter = $(this.name+'Filter');
        this.focused = false;


        // получаем шаблоны
        this.getItemTemplates();

        Event.observe(document, 'keydown', this.keydown.bindAsEventListener(this), false);
        Event.observe(document, 'keyup', this.keyup.bindAsEventListener(this), false);
        Event.observe(this.listHolder, 'click', this.focusOn.bindAsEventListener(this), false);
        Event.observe(document, 'mouseup', this.focusOff.bindAsEventListener(this), false);

        if (this.filter)
            Event.observe(this.filter, 'keyup', this.filterChange.bindAsEventListener(this), false);

        // нажатие клавиши ctrl (нажата или нет)
        this.isCtrl = false;
    },

    // получаем шаблоны строк
    getItemTemplates: function() {
        if (!this.tplTitles)
           return;
        var that = this;
        var descendants = this.listHolder.descendants();
        descendants.each(function(el) {
            that.tplTitles.each(function(tplTitle) {
                if (el.id == tplTitle) {
                    var tempEl = document.createElement(el.parentNode.tagName);
                    tempEl.appendChild(el);
                    var html = tempEl.innerHTML.replace(/#%7B([a-zA-Z0-9_-]+)%7D/gi, "#{$1}")
                    that.itemTemplates[tplTitle] = html;
                    delete tempEl;
                }
            });
        });
    },

    //
    filterChange: function(e) {
        this.focusList(true);
        if (e.keyCode == Event.KEY_UP || e.keyCode == Event.KEY_DOWN) {
            this.filter.blur();
            return;
        }
        if (this.filterText == this.filter.value)
            return;
        this.filterText = this.filter.value;
        if (this.filter.value.length < 2) {
            if (this.clearOnFilter) {
                this.clearList();
                if (this.paging) {
                    this.paging.total = 0;
                    this.paging.write();
                }
                return;
            }
            else
                this.filterText = "";
        }
        this.getList({filter:this.filterText,pageNum:1});
    },

    within: function(e) {
        if (e.pageX == null && e.clientX != null ) {
            var html = document.documentElement
            var body = document.body
            e.pageX = e.clientX + (html && html.scrollLeft || body && body.scrollLeft || 0) - (html.clientLeft || 0);
            e.pageY = e.clientY + (html && html.scrollTop || body && body.scrollTop || 0) - (html.clientTop || 0);
        }
        if (Position.within(this.listHolder, e.pageX, e.pageY))
            return true;
        return false;
    },

    // задавать "фокус" списку по клику
    focusOn: function(e) {
        if (this.within(e))
            this.focusList(true);
    },

    // убирать "фокус" списку по клику
    focusOff: function(e) {
        if (!this.within(e))
            this.focusList(false);
    },

    // задать/убрать "фокус"
    focusList: function(act) {
        if (act) {
            if (this.lists) {
                for (var i = 0; i < this.lists.length; ++i) {
                    var list = window[this.lists[i]];
                    list.focusList(false);
                }
            }
            this.listHolder.addClassName(this.focusedListClass);
            this.focused = true;
        } else {
            this.listHolder.removeClassName(this.focusedListClass);
            this.focused = false;
        }
    },

    // вставить новый элемент в список
    insertItem: function(itemData, mode) {
        var item = new listItem({
            id        : itemData.id,
            data      : itemData,
            list      : this
        });
        item.write(mode);
        this.listItems[itemData.id] = item;
    },

    // очистка списка
    clearList: function() {
        $H(this.listItems).each(function(item) {
            item.value.element.remove();
        });
        this.listItems = {};
        this.selectedItemId = 0;
        if (this.paging) {
            this.paging.total = 0;
            this.paging.write();
        }
    },

    // удаление элемента списка
    removeItem: function(id) {
        this.listItems[id].element.remove();
        delete this.listItems[id];
        if (this.selectedItemId == id)
            this.selectedItemId = 0;
    },

    // убрать выбор(выделение) со всех элементов списка
    unselectAll: function() {
        $H(this.listItems).each(function(item) {
           if (item.value.currentTemplate != 'add') {
               item.value.selected = false;
               item.value.write('view');
           }
        });
        this.selectedItemId = 0;
    },

    // обновить порядковые номера
    refreshNums: function() {
        var i = 1;
        if (this.paging) {
            i = (this.paging.perPage * (this.paging.pageNum - 1)) + 1;
        }
        $H(this.listItems).each(function(item) {
           item.value.data.num = i;
           item.value.write(false, true);
           i++;
        });
    },

    keydown: function(e) {
        if(e.keyCode == 17)
            this.isCtrl = true;

        // перемещение при помощи пейджинга ctrl + left, ctrl + right
        if (this.isCtrl && (e.keyCode != 17) && this.focused && this.paging) {
            Event.stop(e);
            if ((e.keyCode == Event.KEY_LEFT) && (this.paging.pageNum > 1))
                this.getList(Object.extend(this.getParams, {pageNum:this.paging.pageNum-1}));
            if ((e.keyCode == Event.KEY_RIGHT) && (this.paging.pageNum < this.paging.pagesCount))
                this.getList(Object.extend(this.getParams, {pageNum:this.paging.pageNum+1}));
            return;
        }

        if (!(e.keyCode && (e.keyCode == Event.KEY_UP || e.keyCode == Event.KEY_DOWN)) || !this.focused)
            return;
        Event.stop(e);
        var that = this;
        var nav = new Array();
        var curr;
        var i = 0;
        $H(this.listItems).each(function(item) {
            if (item.key == that.selectedItemId)
                curr = i;
            nav[i]= item.key;
            i++;
        });
        prev = nav[curr-1];
        next = nav[curr+1];
        if (!prev)
            prev = nav[nav.length-1];
        if (!next)
            next = nav[0];
        if ((e.keyCode == Event.KEY_UP) && (prev))
            this.listItems[prev].select();
        if ((e.keyCode == Event.KEY_DOWN) && (next))
            this.listItems[next].select();
    },

    keyup: function(e) {
        if(e.keyCode == 17)
            this.isCtrl = false;
    },

    hide: function() {
        this.listHolder.hide();
    },

    show: function() {
        this.listHolder.show();
    },


    // форма добавления нового элемента в список
    addItem: function() {
        if (!this.getParams)
            return;
        inp = this.name+'AddInput';
        if ($(inp))
            $(inp).focus();
        if (this.listItems[0])
            return;
        this.insertItem({id:0}, 'add');
        $(inp).focus();
        Event.observe($(inp), 'keydown', this.doAddKeydown.bindAsEventListener(this), false);

    },

    // вызвать на редактирование
    editItem: function(id, params) {
        if (params)
            Object.extend(this.getParams, params);
        this.focusList(true);
        this.unselectAll();
        var item = this.listItems[id];
        item.write('edit');
        var editInput = $(this.name+'EditInput'+id);
        if (editInput) {
            editInput.focus();
            Event.observe(editInput, 'keydown', this.doEditKeydown.bindAsEventListener(this, id), false);
        }
        this.selectedItemId = id;
    },

    // загрузить список
    getList: function(params) {
        // при использовании пейджинга к params
        // добавлять свойство params.pageNum (номер страницы)

        var that = this;
        this.listHolder.style.display = 'block';
        Object.extend(that.getParams, params);
        Object.extend(params, that.getParams);
        params.mode = 'view';
        params.perPage = this.perPage;

        if (this.loadingImg)
            this.loadingImg.show();

        var r = new Ajax.Request(this.backendScript, {
            method: 'post',
            parameters: params,
            onFailure: function(tr) {
                alert('Ошибка передачи данных');
            },
            onSuccess: function(tr) {
                if (that.loadingImg)
                    that.loadingImg.hide();

                var data = $H(tr.responseJS.data);
                if (tr.responseJS.total) {
                    that.total = tr.responseJS.total;
                }
                that.clearList();
                var i = 1;
                data.each(function(itemData) {
                    itemData.value.num = i;
                    that.insertItem(itemData.value, 'view');
                    i++;
                });
                if (that.onGetScript) {
                    var func = that.onGetScript;
                    func = func.replace(/#\{params\}/g, Object.toJSON(params));
                    func = func.replace(/#\{data\}/g, Object.toJSON(data));
                    eval(func);
                }

                // пейджинг
                if (that.paging) {
                    that.paging.perPage      = that.perPage;
                    that.paging.total        = that.total;
                    that.paging.pageNum      = that.getParams.pageNum;
                    that.paging.scriptParams = that.getParams;
                    that.paging.write();
                    that.refreshNums();
                }
                if ((i < 2) && that.hideIfEmpty)
                    that.listHolder.hide();
                else
                    that.listHolder.show();
            }
        });
    },

    // добавить
    doAdd: function() {
        var that = this;
        var addInput = $(this.name+'AddInput');
        if (!addInput.value) {
            alert('Введите значение');
            addInput.focus();
            return;
        }
        var params = Object.clone(that.getParams);
        params.mode = 'add';
        params.value = addInput.value;
        if (this.loadingImg)
            this.loadingImg.show();
        var r = new Ajax.Request(this.backendScript, {
            method: 'post',
            parameters: params,
            onFailure: function(tr) {
                alert('Ошибка передачи данных');
            },
            onSuccess: function(tr) {
                var data = tr.responseJS.data;
                var item = that.listItems[0];
                item.data = data;
                item.data.num = $H(that.listItems).size();
                that.listItems[data.id] = item;
                delete that.listItems[0];
                item.id = data.id;
                item.currentTemplate = 'view';
                item.select();
                if (that.onAddScript) {
                    var func = that.onAddScript;
                    func = func.replace(/#\{value\}/g, Object.toJSON(params.value));
                    func = func.replace(/#\{data\}/g, Object.toJSON(data));
                    eval(func);
                }
                if (that.loadingImg)
                    that.loadingImg.hide();
            }
        });

    },

    // добавить по нажатию клавиши enter
    doAddKeydown: function(e, id) {
        this.focusList(true);
        if (e.keyCode && (e.keyCode != Event.KEY_RETURN))
            return;
        this.doAdd();
    },

    // отредактировать
    doEdit: function(id) {
        var item = this.listItems[id];
        var that = this;
        var inputElement = $(this.name+'EditInput'+id);
        if (!inputElement.value) {
            alert('Введите значение');
            inputElement.focus();
            return;
        }
        if (this.loadingImg)
            this.loadingImg.show();
        var prms = {};
        Object.extend(prms, this.getParams);
        prms['mode'] = 'edit';
        prms['id'] = id;
        prms['value'] = inputElement.value;
        var r = new Ajax.Request(this.backendScript, {
            method: 'post',
            parameters: prms,
            onFailure: function(tr) {
                alert('Ошибка передачи данных');
            },
            onSuccess: function(tr) {
                var data = tr.responseJS.data;
                Object.extend(item.data, data[id]);
                item.write('select');
                if (that.loadingImg)
                    that.loadingImg.hide();
            }
        });
    },

    // отредактировать по нажатию клавиши enter
    doEditKeydown: function(e, id) {
        if (e.keyCode && (e.keyCode != Event.KEY_RETURN))
            return;
        this.doEdit(id);
    },

    // удалить элемент списка
    doDelete: function(id, params) {
        var that = this;
        this.listItems[id].select();
        if (!confirm('Удалить?'))
            return;
        if (params)
            Object.extend(this.getParams, params);
        if (this.loadingImg)
            this.loadingImg.show();
        var params = Object.clone(that.getParams);
        params.mode = 'del';
        params.id = id;
        var r = new Ajax.Request(this.backendScript, {
            method: 'post',
            parameters: params,
            onFailure: function(tr) {
                alert('Ошибка передачи данных');
            },
            onSuccess: function(tr) {
                var data = tr.responseJS.data;
                if (that.onDeleteScript) {
                    var func = that.onDeleteScript;
                    func = func.replace(/#\{data\}/g, Object.toJSON(data));
                    eval(func);
                }
                that.removeItem(id);
                that.refreshNums();
                if (that.loadingImg)
                    that.loadingImg.hide();
            }
        });
    }
};