var SpecTable = Class.create({
    initialize: function(table_id, json_object) {
        this.spec_table = $(table_id);
        this.spec_table_data = json_object;
        this.suppress_render = false;
        this.render_table();
    },
    
    create_table: function() {
        this.suppress_render = true;
        
        (2).times(function() {
            this.add_column();
            this.add_row();
        }.bind(this));
        
        this.suppress_render = false;
        this.render_table();
    },
    
    render_table: function() {
        if (this.no_columns()) {
            span = Builder.node('span', { className: 'create-spec-table' }, 'Create Specifications Table' );
            p = Builder.node('p', { id: 'spec-table' }, span );
            span.observe('click', this.create_table.bind(this));
            this.spec_table.replace(p);
            this.spec_table = $('spec-table'); // take control of spec_table again seeing as we just replaced it
        } else if (!this.suppress_render) {
            var thead_row = Builder.node('tr');
            var tbody_rows = $(new Array);
            
            this.spec_table_data['columns'].each(function (column, column_index) {
                thead_row.appendChild(Builder.node('th', { id: 'spec-table-column-' + column_index }, [
                    Builder.node('input', { type: 'text', className: 'text', id: 'spec-table-column-name-' + column_index, value: column['name'] }),
                    Builder.node('span', { className: 'remove-column' }, 'Remove Column')
                ]));
                
                this.spec_table_data.num_rows.times(function(row_index) {
                    if (!tbody_rows[row_index]) tbody_rows[row_index] = Builder.node('tr', { id: 'spec-table-row-' + row_index });
                    
                    tbody_rows[row_index].appendChild(Builder.node('td', Builder.node('input', {
                        type: 'text',
                        className: 'text',
                        id: 'spec-table-cell-' + column_index + '-' + row_index,
                        value: column.rows[row_index]
                    })));
                });
            }.bind(this));
            
            thead_row.appendChild(Builder.node('th', Builder.node('span', { id: 'add-column', className: 'add-column' }, 'Add Column')));
            
            tbody_rows.collect(function(row) {
                row.appendChild(Builder.node('td', Builder.node('span', { className: 'remove-row' }, 'Remove')));
            });
            
            tbody_rows.push(Builder.node('tr',
                Builder.node('td', { colspan: this.spec_table_data.columns.size() + 1 },
                    Builder.node('span', { id: 'add-row', className: 'add-row' }, 'Add Row' )
                ))
            );
            
            var thead = Builder.node('thead', thead_row);
            var tbody = Builder.node('tbody', tbody_rows.toArray());
            var table = Builder.node('table', { id: 'spec-table', className: 'add-product-table' }, [ thead, tbody ]);
            
            this.spec_table.replace(table);
            this.spec_table = $('spec-table'); // take control of spec_table again seeing as we just replaced it
            
            // bind click listeners for table controls
            $('add-column').observe('click', this.add_column.bind(this));
            $('add-row').observe('click', this.add_row.bind(this));
            
            $$('span.remove-column').each(function(element) {
                element.observe('click', this.remove_column.bind(this));
            }.bind(this));
            
            $$('span.remove-row').each(function(element) {
                element.observe('click', this.remove_row.bind(this));
            }.bind(this));
            
            // bind change listeners for table inputs
            $$('#spec-table thead input').each(function(element) {
                element.observe('change', this.update_column_name.bind(this));
            }.bind(this));
            
            $$('#spec-table tbody input').each(function(element) {
                element.observe('change', this.update_cell.bind(this));
            }.bind(this));
        }
    },
    
    to_json: function() {
        return Object.toJSON(this.spec_table_data);
    },
    
    disable: function() {
        $$('#spec-table input').invoke('disable');
    },
    
    no_columns: function() {
        return this.spec_table_data.columns.size() <= 0;
    },
    
    update_column_name: function(event) {
        var input = event.element()
        var index = input.id.gsub('spec-table-column-name-', '');
        this.spec_table_data.columns[index].name = input.value;
    },
    
    update_cell: function(event) {
        var input = event.element();
        var indices = input.id.match(/^spec-table-cell-(\d+)-(\d+)$/);
        var column_index = indices[1];
        var row_index = indices[2];
        this.spec_table_data.columns[column_index].rows[row_index] = input.value;
    },
    
    add_column: function() {
        var rows = new Array();
        
        this.spec_table_data.num_rows.times(function(n) {
            rows.push('');
        });
        
        var new_column = {
            name: '',
            rows: rows
        };
        
        this.spec_table_data.columns.push(new_column);
        this.render_table();
    },
    
    remove_column: function(event) {
        var index = event.element().up('th').id.gsub('spec-table-column-', '');
        this.spec_table_data.columns.splice(index, 1);
        
        // nuke num_rows if there are no columns left
        if (this.no_columns()) {
            this.spec_table_data.num_rows = 0;
        }
        
        this.render_table();
    },
    
    add_row: function() {
        // only bother if there are actually columns to add rows to
        if (!this.no_columns()) {
            this.spec_table_data.num_rows++;
            
            this.spec_table_data.columns.each(function(column) {
                column.rows.push('');
            });
            
            this.render_table();
        }
    },
    
    remove_row: function(event) {
        this.spec_table_data.num_rows--;
        
        var index = event.element().up('tr').id.gsub('spec-table-row-', '');
        
        this.spec_table_data.columns.each(function(column) {
            column.rows.splice(index, 1); // javascript in all its glory - this actually deletes an element from the middle of an array!
        });
        
        this.render_table();
    },
});
