document.observe('dom:loaded', function(){
    $$(GridSelector).each(function(e){
        if (Object.isUndefined(e.control)) new GridControl(e)
    });
});

var GridSelector = '.gridsolo';
var GridControl = Class.create(FormControl, {
    selector:GridSelector,
    newIndex:null,
    rowSelector:null,
    cellSelector:null,
    filterSelector:null,
    actionSelector:null,
    actionRowSelector: null,
    editboxSelector:null,
    fieldSelect:null,

    initialize: function($super, element)
    {
        this.newIndex = 0;
        this.rowSelector = '.row';
        this.cellSelector = '.cell';
        this.filterSelector = '.filter';
        this.actionSelector = '.action_item';
        this.actionRowSelector = this.rowSelector +' '+ this.actionSelector;
        this.editboxSelector = '.editbox';
        $super(element);
        this.fieldSelect = this.view.getAttribute('fieldselect');
    },

    ajaxComplete: function()
    {
        this.view.find(GridSelector).each(function(e){new GridControl(e)});

        //init gridlist
        if (this.view.next())
            this.view.next().find(GridSelector).each(function(e){new GridControl(e)});
    },

    setFilter: function(key, value)
    {
        this.setValue(this.findOne(this.filterSelector+'.field-'+key+' .box'), value);
    },

    observeEvent: function($super)
    {
        $super();
        this.observeRows();
        this.observeBasicActions();
        this.observeFilter();
        this.observeSelectActions();
        this.observeMassActions();
        this.observeColumnResize();
    },

    getSelectedRowIds: function()
    {
        var control = this;
        var ids = new Array();
        this.findRow('.selected').each(function(e){
            ids.push(control.getRecordId(e));
        });
        return ids;
    },

    getSelectedRows: function()
    {
        return this.findRow('.selected');
    },

    getRecordId: function(row)
    {
        return row.getAttribute('key');
    },

    findRow: function(selector)
    {
        selector = Object.isUndefined(selector) ? '' : selector;
        return this.find(this.rowSelector + selector);
    },

    findCell: function(selector)
    {
        selector = Object.isUndefined(selector) ? '' : selector;
        return this.find(this.cellSelector + selector);
    },

    findFilter: function(selector)
    {
        selector = Object.isUndefined(selector) ? '' : selector;
        return this.find(this.filterSelector + selector);
    },

    observeRows: function()
    {
        var control = this;
        this.findRow(':nth-child(2n)').invoke('addClassName', 'alternate');
        this.findRow().invoke('observe', 'click', function(event){control.toggleRowSelect(this, event)});
        this.findRow(' input.check[type="checkbox"]').invoke('observe', 'click', function(event){control.checkboxClick(this, event)});
        this.findRow(' .thumbimg').each(function(e){
            var cell = e.up(control.cellSelector);
            var src = cell.getAttribute('value');
            new Tooltip(cell, '<img class="tooltip_img" src="'+src+'" />')
        });

        this.find(this.actionRowSelector+'.delete').invoke('observe', 'click', function(event){control.deleteItem(this, event)});
        this.find(this.actionRowSelector+'.inline_edit').each(function(e){
            e.toggleRowEdit = control.toggleRowEdit;
            e.observe('click', control.toggleRowEdit);
        });

        this.findCell().each(function(e){
            var i = e.down('.box');
            if (i) i.observe('change', control.inputChanged);

            e.observe('click', function(event){
                if (event.altKey){
                    this.toggleClassName('selected');
                    event.stopPropagation();
                }
            })
            e.observe('dblclick', function(event){
                control.toggleCellEdit(this);
                event.stopPropagation();
            })
            if (e.hasClassName('oneclickedit'))
                e.observe('click', function(event){
                    if (!this.hasClassName('editing')) control.enableCellEdit(e);
                    event.stopPropagation();
                })
        });

        this.observeActionBox();
    },

    observeBasicActions: function()
    {
        var control = this;
        this.view.control = this;
        this.find('input.check_all').invoke('observe', 'click', function(){control.setAllCheckbox(this.checked)});
        this.find('.pager select').invoke('observe', 'change', function(){control.refresh()});
        this.find('.pager .page').invoke('observe', 'click', function(){
            var page = this.value;
            control.find('.pager_input').each(function(e){
                e.value = page;
            });
            control.refresh()
        });
        this.find('.sortable').invoke('observe', 'click', function(){control.sortColumn(this)});
    },

    observeFilter: function()
    {
        var control = this;
        this.findFilter(' .box').each(function(e){
            e.originValue = e.value;
            e.observe('change', control.inputChanged);
            if (e.value) e.addClassName('filtered');
        })

        this.findFilter(' select').invoke('observe', 'change', function(){
            control.refresh()
        });

        this.find('.clear_filter').invoke('observe', 'click', function(){control.clearFilter()});
        this.findFilter(' input.daterange_picker').each(function(e){
            var dr = new DaterangeControl(e);
            dr.applyCallback = function(){
                control.refresh();
            }
        });

        this.findFilter(' '+GridSelectSelector).each(function(e){
            if (Object.isUndefined(e.control))
            {
                new GridselectControl(e);
                e.control.observe('rowselect', function(){control.refresh()});
            }
        });
    },

    observeActionBox: function()
    {
        this.findRow(' .actionbox').each(function(e){
            if (e.down('.action_wrapper')){
                e.observe('mouseover', function(){
                    this.down('div.action_wrapper').show();
                });
                e.observe('mouseout', function(){
                    this.down('div.action_wrapper').hide();
                });
            }
        });
    },

    observeColumnResize: function()
    {
        this.find('thead .caption th').each(function(e){
			new ResizerW(e);
            e.setStyle({width:e.getStyle('width')});
        });
        updateAllResizers();
    },

    observeSelectActions: function()
    {
        var control = this;
        this.find('.select_all').invoke('observe', 'click', function(){
            control.selectAll();
        });

        this.find('.select_none').invoke('observe', 'click', function(){
            control.selectNone();
        });

        this.find('.select_editing').invoke('observe', 'click', function(){
            control.selectEditing();
        });

        this.find('.select_inverse').invoke('observe', 'click', function(){
            control.selectInverse();
        });
    },

    observeMassActions: function()
    {
        var control = this;
        this.find('.add_new').invoke('observe', 'click', function(){
            control.addNew();
        });

        this.find('.add_similar').invoke('observe', 'click', function(){
            control.addSimilar();
        });

        this.find('.copy_topdown').invoke('observe', 'click', function(){
            control.copyTopdown();
        });

        this.find('.toogle_edit').invoke('observe', 'click', function(){
            control.editSelected();
        });

        this.find('.mass_action').invoke('observe', 'click', function(){
            var action = this.getAttribute('action');
            var confirm = !this.hasClassName('noconfirm');
            var selected_check = !this.hasClassName('noselected');
            var file_export = this.hasClassName('file_export');
            control.actOnSelecteds(action, confirm, selected_check, file_export, this.innerHTML);
        });
    },

    formBeforeSubmit: function()
    {
        this.removeUnchangedFilter();
        this.find(this.editboxSelector).invoke('remove');
    },

    removeUnchangedInputs: function()
    {
        var control = this;
        this.findRow('.editing .inline_edit').each(function(e){
            if (!e.up(control.rowSelector).down('.changed') && e.toggleRowEdit)
                e.toggleRowEdit();
        });
        this.findCell('.editing input:not(.changed)').each(function(e){control.undoEdit(e)});
        this.findCell('.editing select:not(.changed)').each(function(e){control.undoEdit(e)});
        this.findCell('.editing input[type=checkbox].changed').each(function(e){control.undoCheckboxEdit(e)});
    },

    removeUnchangedFilter: function()
    {
        this.findFilter(' .box').each(function(e){ if(e.value=='') e.disable()});
    },

    undoCheckboxEdit: function(checkbox)
    {
        var cell = checkbox.up(this.cellSelector);
        if (cell.hasClassName('keepedit')) return;

        checkbox.hide().checked = true;
        cell.insert(checkbox.value);
    },

    undoEdit: function(input)
    {
        this.cancelCellEdit(input.up(this.cellSelector));
    },

    checkForChanges: function()
    {
        var control = this;
        this.findCell('.editing input:not(.changed)').each(function(e){
            if (e.value != e.up(control.cellSelector).getAttribute('value')){
                e.addClassName('changed');
            }
        });
        this.removeUnchangedInputs();
        var changes = this.findCell('.editing .box.changed').length;
        return changes>0;
    },

    checkForFilterChanges: function()
    {
        this.findFilter('.editing .box').each(function(e){
            if (e.value != e.originValue) e.addClassName('changed');
            else e.removeClassName('changed');
        });
        var changes = this.findFilter('.editing input.changed').length;

        return changes>0;
    },

    editSelected: function()
    {
        this.findRow('.selected .inline_edit').invoke('toggleRowEdit');
        //this.findCell('.selected.editable').each(this.toggleCellEdit);
    },

    toggleCellEdit: function(e)
    {
        if (!e.hasClassName('editable')) return;
        var editing = e.hasClassName('editing');
        if (!editing) this.enableCellEdit(e);
        else this.cancelCellEdit(e);
        updateAllResizers();
    },

    toggleRowEdit: function(event)
    {
        var control = this.up('.grid').control;
        var row = this.up(control.rowSelector);
        var cells = row.find(control.container + control.cellSelector+'.editable');
        var editing = row.hasClassName('editing');
        if (!editing)
        {
            cells.each(function(e){control.enableCellEdit(e)});
            row.addClassName('editing');
            this.update('Cancel');
        }
        else
        {
            cells.each(control.cancelCellEdit);
            row.removeClassName('editing');
            this.update('Edit');
        }
        if (event) event.stopPropagation();
        updateAllResizers();
    },

    enableCellEdit: function(cell)
    {
        this.saveCellFormatedValue(cell);
        var cell_value = cell.getAttribute('value');
        var editbox = this.getEditbox(cell, cell_value);

        var i = cell.addClassName('editing').update(editbox).down('.box').observe('change', this.inputChanged);

        if (i.type!='checkbox')
        {
            i.value = i.originValue = cell_value;
            if (i.getAttribute('type')=='datetime')
            {
                this.initDatepicker(i);
            }
            else if (i.hasClassName('gridselect_ready'))
            {
                i.addClassName('gridselect');
                new GridselectControl(i);
            }
        }
        this.fire('celledit', {cell: cell});
    },

    getEditbox: function(cell, cell_value)
    {
        var editbox_template = this.findOne(this.editboxSelector+' .edit-'+cell.getAttribute('field'));
        var id = this.getRecordId(cell.up(this.rowSelector));

        var editbox = editbox_template.innerHTML.gsub(/#id/, id).gsub(/#v/, cell_value);
        var display = cell.down('.displayvalue');
        display = display ? display.innerHTML : '';
        editbox = editbox.gsub(/#f/, display);

        var checked = cell_value>0 ? 'checked="checked"' : '';
        return editbox.gsub(/#checked/, checked);
    },

    saveCellFormatedValue: function(e)
    {
        if (!e.formated){
            var value = e.down();
            e.formated = value ? value : e.innerHTML;
        }
    },

    initDatepicker: function(e)
    {
        e.observe('click', function(){
            new CalendarDateSelect(this);
        }).observe('blur', this.inputChanged)
    },

    cancelCellEdit: function(cell)
    {
        if (cell.hasClassName('keepedit')) return;
        cell.removeClassName('editing').update(cell.formated);
    },

    inputChanged: function()
    {
        if (this.type=='checkbox') this.value = this.checked ? 1:0;

        if (this.value != this.originValue)
            this.addClassName('changed');
        else
            this.removeClassName('changed');
    },

    clearFilter: function()
    {
        var control = this;
        this.find('.filter input', '.filter select').each(function(e){
            control.setValue(e, '')
        });
        this.refresh();
    },

    sortColumn: function(e)
    {
        var sort_order = this.findOne('.sort_order');
        var sort_field = this.findOne('.sort_field');

        if (e.hasClassName('asc')) this.setValue(sort_order, 'desc');
        else if(e.hasClassName('desc')) this.setValue(sort_order, '');
        else this.setValue(sort_order, 'asc');
        this.setValue(sort_field, sort_order.value? e.title:null);
        this.refresh();
    },

    discardAllChanges: function()
    {
        var control = this;
        this.findRow('.editing .inline_edit').each(function(e){
            if (e.toggleRowEdit) e.toggleRowEdit();
        })
        this.findCell('.editing').each(function(e){
            control.cancelCellEdit(e);
        })
    },

    actOnSelecteds: function(action, confirmRequired, selected_check, file_export, label)
    {
        if (!label) label = action;
        if (selected_check && this.getSelectedRows().length < 1) {alert('No item selected!');return;}
        if (confirmRequired && !confirm('Do you want to `'+label+'` selected items?')) return;
        this.setFormAction(action);

        if (file_export) {
            this.submitFormNoajax();
            this.setFormAction('');
        }
        else
            this.refresh();
    },

    processAction: function(action)
    {
        this.setFormAction(action).refresh();
    },

    deleteItem: function(e, event)
    {
        this.selectNone();
        var row = e.up(this.rowSelector);
        row.addClassName('editing');
        this.selectRow(row, true);
        if (confirm('Do you want to delete this item?'))
        {
            this.setFormAction('delete');
            this.refresh();
        }
        else
            row.removeClassName('editing');
        event.stopPropagation();
    },

    checkboxClick: function(e, event)
    {
        var row = e.up(this.rowSelector);
        if(e.checked)
            row.addClassName('selected')
        else
            row.removeClassName('selected')
        event.stopPropagation();
    },

    toggleRowSelect: function(e, event)
    {
        var element = event.element();
        if (element.tagName != 'INPUT'
            && element.tagName != 'SELECT'
            && !element.hasClassName('node_icon')
            && !element.hasClassName('action_item'))
        {
            var c = e.down('input'+this.container+'.check[type="checkbox"]');
            if (c) this.selectRow(e, !c.checked, c);
        }

        var id = this.getRecordId(e);
        var display = this.fieldSelect ? this.getFieldValue(e, this.fieldSelect) : id;
        this.fire('rowselect', {id:id, display:display});
    },

    getFieldValue: function(row, fieldname)
    {
        return row.down('.cell[field='+fieldname+']').getAttribute('value');
    },

    setAllCheckbox: function(checked)
    {
        var control = this;
        this.findRow().each(function(row){
            control.selectRow(row, checked)
        });
    },

    selectRow: function(row, checked, e)
    {
        if (!e) e = row.down('input[type="checkbox"]');
        e.checked = checked;
        if(e.checked)
            row.addClassName('selected')
        else
            row.removeClassName('selected')
    },

    selectAll: function()
    {
        this.findOne('input.check_all').checked = true;
        this.setAllCheckbox(true);
    },

    selectNone: function()
    {
        this.find('input.check_all[type="checkbox"]').first().checked = false;
        this.setAllCheckbox(false);
        this.findCell('.selected').each(function(e){e.removeClassName('selected')});
    },

    selectEditing: function()
    {
        var control = this;
        this.findRow().each(function(row){control.selectRow(row, false)});
        this.findRow('.editing').each(function(row){control.selectRow(row, true)});
        this.findRow(':not(.selected) '+this.cellSelector+'.editing').each(function(e){e.toggleClassName('selected')});
    },

    selectInverse: function()
    {
        var control = this;
        var selected = this.getSelectedRows();
        this.findRow(':not(.selected)').each(function(row){control.selectRow(row, true)});
        selected.each(function(row){control.selectRow(row, false)});
    },

    addNew: function()
    {
        var control = this;
        var new_id = "new_" + this.newIndex++;
        this.findOne('tbody').insert('<tr class="row addnew editing '+new_id+'" key="'+new_id+'"></tr>')
        var editbox = this.findOne(this.editboxSelector);

        var row = this.findOne('.'+new_id);
        row.update(editbox.innerHTML);

        row.find(this.container+this.cellSelector+'.editable').each(function(e)
        {
            e.update('');
            control.enableCellEdit(e);
            var box = e.down('.box');
            var filter = control.findOne(control.filterSelector+'.field-'+e.getAttribute('field')+' select');
            if (filter && filter.value) box.value = filter.value;

            if (box.value && box.value != '#NULL') box.addClassName('changed');

            filter = control.findOne(control.filterSelector+'.field-'+e.getAttribute('field')+' '+GridSelectSelector);
            if (filter)
            {
                box = e.down(GridSelectSelector);
                if (box && (filter.value != ''))
                {
                    box.control.setValue(filter.value);
                    box.control.setDisplayValue(filter.getAttribute('display'));
                }
            }
        });

        var cancel = row.down('.inline_edit');
        cancel.toggleRowEdit = function(){this.up(control.rowSelector+'.editing').remove()};
        cancel.observe('click', function(){this.toggleRowEdit()});
    },
   addNew2: function()
    {
        var control = this;
        var new_id = "new_" + this.newIndex++;
        this.findOne('tbody').insert('<tr class="row addnew editing '+new_id+'" key="'+new_id+'"></tr>')
        var editbox = this.findOne(this.editboxSelector);

        var row = this.findOne('.'+new_id);
        row.update(editbox.innerHTML);

        row.find(this.container+this.cellSelector+'.editable').each(function(e)
        {
            e.update('');
            control.enableCellEdit(e);
            var box = e.down('.box');
            var filter = control.findOne(control.filterSelector+'.field-'+e.getAttribute('field')+' select');
            if (filter && filter.value)
            {
             box.value = filter.value;
			}
			else
			{
			    filter = control.findOne(control.filterSelector+'.field-'+e.getAttribute('field')+' input');
                if (filter && filter.value) box.value = filter.value;
			}
            if (box.value && box.value != '#NULL') box.addClassName('changed');

            filter = control.findOne(control.filterSelector+'.field-'+e.getAttribute('field')+' '+GridSelectSelector);
            if (filter)
            {
                box = e.down(GridSelectSelector);
                if (box && (filter.value != ''))
                {
                    box.control.setValue(filter.value);
                    box.control.setDisplayValue(filter.getAttribute('display'));
                }
            }
        });

        var cancel = row.down('.inline_edit');
        cancel.toggleRowEdit = function(){this.up(control.rowSelector+'.editing').remove()};
        cancel.observe('click', function(){this.toggleRowEdit()});
    },

    addSimilar: function()
    {
        var last_row = this.getLastNewRow();
        this.addNew();
        var new_row = this.getLastNewRow();
        this.copyRow(last_row, new_row);
    },

    copyTopdown: function()
    {
        var control = this;
        var first_row = this.getFirstNewRow();
        this.findRow('.addnew').each(function(e){
            control.copyRow(first_row, e);
        });
    },

    getFirstNewRow: function()
    {
        return this.findRow('.addnew').first();
    },

    getLastNewRow: function()
    {
        return this.findRow('.addnew').last();
    },

    copyRow: function(src, dest)
    {
        src.find(' .cell').each(function(e){
            var box = e.down('.box');
            if (box.value && box.value != '#NULL')
            {
                var field = e.getAttribute('field');
                var dest_box = dest.find(' .cell[field='+field+'] .box').first();
                dest_box.value = box.value
                dest_box.addClassName('changed');
            }
        });
    }
});

