var tableView = Class.create();
tableView.prototype = {
    initialize: function(params) {
        // все ячейки таблицы
        this.cells = new Array();
        // ячейка таблицы, в которой содержится шаблон отображения данных
        this.cell = false;
        // таблица (определяется по cellTpl)
        this.table = false;
        // количество колонок в таблице
        this.cols = 1;
        // данные в формате массива, ячейка массива это объект "имя"=>"значение"
        this.data = false;
        // имя шаблона для отображения данных
        this.viewTpl = false;
        Object.extend(this, params);

        // в объект this.cellsTpl помещаем клоны ячеек, по соответствующему id
        // например cellsTpl.addDataCell = <клон ячейки>
        var that = this;
        this.cellsTpl.each(function(cell) {
            var cl = $(cell);
            if (!cl)
                return;
            that.cellsTpl[cell] = cl.cloneNode(true);
            if (!that.table)
                that.table = cl.up('table');
        });
    },

    // заполняем ячейки массивом данных
    fill: function() {
        var that = this;
        var data = $H(this.data);
        var tpl = new Template(this.cellsTpl[this.viewTpl].innerHTML.replace(/#%7B([a-zA-Z0-9_-]+)%7D/gi, "#{$1}"));
        var i = 0;
        // удаляем все ячейки
        this.cells.clear();
        data.each(function(item){
            var newCell = that.cellsTpl[that.viewTpl].cloneNode(true);
            that.cells.push(newCell);
            Object.extend(item.value, {counter: parseInt(i)+1});
            newCell.update(tpl.evaluate(item.value));
            i++;
        });
        this.rebuild();
    },

    // создать ячейку
    newCell: function(tpl) {
        var newCell = this.cellsTpl[tpl].cloneNode(true);
        this.cells.push(newCell);
        this.rebuild();
        return newCell;
    },

    // изменить ячейку
    changeCell: function(cell, tpl) {
        var ind = this.cells.indexOf(cell);
        this.cells[ind] = this.cellsTpl[tpl].cloneNode(true);
        this.rebuild();
        return this.cells[ind];
    },

    // закрыть ячейку (удалить из таблицы)
    closeCell: function(caller) {
        var that = this;
        var cl = this.findCell(caller);
        that.cells = that.cells.without(cl);
        this.rebuild();
        return cl;
    },

    // закрыть все ячейки (удалить из таблицы)
    removeCells: function(caller) {
        this.cells.clear();
        this.rebuild();
    },

    // найти ячейку по внутреннему элементу
    findCell: function(insideElement) {
        return this.cells.find(function(cell){
            if (insideElement.descendantOf(cell))
                return cell;
        });
    },

    // строим таблицу
    rebuild: function() {
        this.table.hide();
        if (!this.cells.length)
            return;
        var that = this;
        // удаляем строки таблицы
        this.table.getElementsBySelector('tr').invoke('remove');
        var cellsCount = this.cells.length;
        var fullCells = this.cols*Math.ceil(cellsCount/this.cols);
        var newTr, rowCount = 0, i = 0;
        this.cells.each(function(item){
             // вставить строку
            if (Math.ceil(i/that.cols) == (i/that.cols)) {
                newTr = that.table.insertRow(rowCount);
                rowCount++;
            }
            newTr.appendChild(item);
            i++;
        });
        // добавить пустые ячейки, если необходимо
        while (i < fullCells) {
            var newCell = this.cells[0].cloneNode(true);
            newTr.appendChild(newCell);
            newCell.update('&nbsp;');
            i++;
        }
        this.table.show();
    }
};