﻿var IPEditorData = Class.create();

IPEditorData.prototype = {
    initialize: function (field, idField, table, recordId, elementId) {
        this.field = field;
        this.idfield = idField;
        this.table = table;
        this.id = recordId;
        this.element = elementId;
        this.editor = null;
    },

    getParameters: function () {
        return 'update.aspx?field=' + this.field + '&idfield=' + this.idfield + '&table=' + this.table + '&id=' + this.id;
    }
};


var TableView = Class.create();

TableView.prototype = {
    initialize: function (element, target, options) {
        this.target = target;
        this.element = element;
        this.columns = [];
        this.editors = [];

        this.refresher = null;

        this.options = {
            obid: 0,
            otid: 0,
            canFilter: true,
            canGroup: true,
            rowsPerPage: 20,
            currentPage: 1,
            numOfPages: 1,
            numOfItems: 0,
            hasheader: 1,
            hasfooter: 1,
            callback: 'getpage',
            columnCount: 1,
            sortby: '',
            groupby: '',
            multiSelect: 'false',
            refresh: 0,
            extradata: ''
        };

        Object.extend(this.options, options || {});

        this.requestData();
    },


    // set up a string with all the criteria needed from the object such as page number, filters, grouping
    getCriteria: function () {
        var crit = this.options.currentPage + ';';      // add page number
        crit += this.options.sortby + ';';              // sort by column
        crit += this.options.groupby + ';';              // group by column
        crit += this.options.columnCount + ';';         // number of columns
        crit += this.options.rowsPerPage + ';';
        this.columns.each(function (c) {                 // filter crit for each column
            if (c.filterText != '') {
                crit += c.colname + ';' + c.filterText + ';';
            }
        });

        return crit;
    },


    // query the server which will return a csv document with the currently filtered data
    requestExport: function () {

        // send the export request
        $('if1').src = 'requests.aspx?obid=' + this.options.obid + '&otid=' + this.options.otid + '&verb=' + this.options.callback + 'export&param1=' + this.getCriteria() + '&param2=' + this.options.extradata;
    },


    // query the server for new data according to criteria
    requestData: function () {
        incLoadingStatus();

        // run end scripts to remove in-place editor controls
        try {
            this.editors.clear();

            //this.editors.each(function (c) {
            //    c.editor.destroy();
            //}, this);
        }
        catch (e) {
            alert('Error.TableView.RequestData: ' + e.Message);
        }


        // send the data request to the server
        new Ajax.Request('requests.aspx?obid=' + this.options.obid + '&otid=' + this.options.otid + '&verb=' + this.options.callback + '&param1=' + this.getCriteria() + '&param2=' + this.options.extradata, { onSuccess: this.receiveData.bindAsEventListener(this), onFailure: this.receiveError.bindAsEventListener(this) });
    },


    // receive data from the server after a request
    receiveData: function (data) {
        decLoadingStatus();

        var respText = data.responseText.gsub('"', '\\"').gsub('\'', '"');
        respText = respText.replace(/(\r\n|\n|\r)/gm, " ");
        respText = respText.replace(/\s+/g, " ");

        var json = respText.evalJSON();
        var c;
        this.options.columnCount = json.colcount;
        this.options.numOfItems = json.recCount;
        this.options.refresh = json.options.refresh;

        this.options.multiSelect = json.options.multiSelect;
        this.options.hasheader = json.options.hasheader;
        this.options.hasfooter = json.options.hasfooter;

        var mod = this.options.numOfItems % this.options.rowsPerPage;
        var np = (this.options.numOfItems - mod) / this.options.rowsPerPage;

        if (mod > 0)
            mod = 1;

        this.options.numOfPages = np + mod;

        // ensure that the class doesn't try to display a page that doesn't exist
        if (this.options.currentPage > this.options.numOfPages) {
            this.options.currentPage = this.options.numOfPages;
        }

        if (this.options.currentPage == 0) {
            this.options.currentPage = 1;
        }

        // get columns    
        this.columns.clear();
        for (i = 1; i <= this.options.columnCount; i++) {
            c = eval('json.columns.col' + i);
            this.columns.push(c);
        }

        this.drawTable(json.data);
    },


    receiveError: function (data) {
        decLoadingStatus();

        alert('Error:' + data.responseText);
    },


    drawTable: function (data) {

        var elname = this.element;
        var code = '<table id="' + elname + '_t" class="ttable">';
        var script = '';
        var d;
        var i;
        var hlink;
        var hlink2;
        var c;
        var todisplay;
        var otid;
        var cda;
        var sel;
        var subId;

        var ms = this.options.multiSelect;
        var sb = this.options.sortby;
        var gb = this.options.groupby;
        var gbcounter = 0;
        var gbindex = 0;
        var gbcaption;

        // add column headers
        code += '<thead>';

        if (this.options.hasheader == 'true') {
            code += '<tr>';

            this.columns.each(function (c) {
                if (c.caption == '') {

                    code += '<td class="theader">';

                    if (ms == 'true') {
                        code += '<input type="checkbox" onclick="var cs =this.checked;selectRows( \'' + elname + '_t\', cs);">';
                        ms = 'false';
                    }

                    gbcounter += 1;

                    code += ' </td>';
                }
                else {

                    if (gb == c.colname) {
                        gbindex = gbcounter;
                        gbcaption = c.caption;
                    }

                    code += '<td class="theader">';
                    code += '<span onclick="' + elname + '.setSortBy(\'' + c.colname + '\');">' + c.caption + '</span>';
                    code += '<img onclick="' + elname + '.setGroupBy(\'' + c.colname + '\');" title="Group by this column" src="icons/groupby.png" alt="Group by"/>';
                    if (sb == c.colname) {
                        code += '<img onclick="' + elname + '.setSortBy(\'' + c.colname + '\');" title="Click to sort descending" src="icons/arrow_down.png" alt="Sort descending"/>';
                    }
                    if (sb == c.colname + " desc") {
                        code += '<img onclick="' + elname + '.setSortBy(\'' + c.colname + '\');" title="Click to sort ascending" src="icons/arrow_up.png" alt="Sort ascending"/>';
                    }
                    code += '</td>';

                    gbcounter += 1;
                }
            });
            code += '</tr>';
        }


        // show filter row
        if (this.options.canFilter) {
            code += '<tr class="filterrow">';
            this.columns.each(function (c) {

                //if (c.colname != gb || gb == '') {
                code += '<td>';

                if (c.canfilter == 'True') {
                    if (c.combodata != null) {
                        code += '<select id="' + elname + '_' + c.colname + '" value="' + c.filterText + '" style="width:100px;" onchange="' + elname + '.catchFilter();" >';

                        cda = Object.values(c.combodata);
                        subId = '';

                        cda.each(function (c2) {

                            if (c2.subId != '') {
                                if (subId != c2.id) {
                                    subId = c2.id;
                                    sel = (c.filterText == c2.id ? 'selected="selected"' : '');
                                    code += '<option ' + sel + ' value = "' + c2.id + '" class="optionhighlight">' + c2.value + '</option>';
                                }

                                sel = (c.filterText == c2.subId ? 'selected="selected"' : '');
                                code += '<option ' + sel + ' value = "' + c2.subId + '" class="optionsubitem">' + c2.subValue + '</option>';
                            }
                            else {
                                sel = (c.filterText == c2.id ? 'selected="selected"' : '');
                                code += '<option ' + sel + ' value = "' + c2.id + '">' + c2.value + '</option>';
                            }
                        });

                        code += '</select>';
                    }
                    else {  // autocompleter filter
                        if (c.autofilterqry != '') {
                            var afid = elname + '_' + c.colname;
                            code += '<input id="' + afid + '" type="hidden" value="' + c.filterId + '">';
                            code += '<input id="auto_' + afid + '" type="text" value="' + c.filterText + '">';
                            code += '<span id="indicator_' + afid + '" class="clear" style="display: none;"><img src="theme/spinner_small.gif" alt="Working..." /></span>';
                            code += '<div id="choices_' + afid + '" class="autocompletenarrow"></div>';
                            code += '<span class="grayedit clickable" title="Clear this filter\'s selection" onclick="' + elname + '.clearAutoFilter(\'' + afid + '\');">Clear</span>'
                            script += 'new Ajax.Autocompleter("auto_' + afid + '", "choices_' + afid + '", "query.aspx", { paramName: "value2", minChars: 2, indicator: "indicator_' + afid + '", parameters: "type=filterdata;' + c.autofilterqry + ';' + c.autofilterfield + '", afterUpdateElement: this.catchAutoFilter.bindAsEventListener(this) });';
                        }
                        //                        else {
                        //                            if (1 == 1) {
                        //                                var afid = elname + '_' + c.colname;
                        //                                code += '<input id="' + afid + '" type="hidden" value="' + c.filterId + '">';
                        //                                code += '<span id="text_' + afid + '" value="' + c.filterText + '"></span>';
                        //                                code += '<div id="loc_' + afid + '"></div>';
                        //                                code += '<img src="icons/search16.png" onclick="' + elname + '.showNumberFilter(\'' + afid + '\');" alt="Filter..." />';
                        //                            }
                        else { // normal filter
                            code += '<input id="' + elname + '_' + c.colname + '" value="' + c.filterText + '" type="text" style="width:65px;">';
                            //                            }
                        }
                    }
                }

                code += '</td>';
                //}
            });
            code += '</tr>';
        }

        code += '</thead><tbody>';


        var cellId;
        var cellValue;
        var hint;
        var currentColumn;
        var oldgb = '';
        var gbcounter;
        var valueCounter;
        var columnVerb = '';
        var columnType = '';
        var prevd;

        // show data
        if (this.options.numOfItems != 0) {
            for (i = 1; i <= (this.options.columnCount * this.options.rowsPerPage); i++) {

                if (i % this.options.columnCount == 1) {

                    // check if must groupby
                    if (gb != '') {
                        d = eval('data.d' + (i + gbindex));
                        if (d == null)
                            break;

                        cellValue = (d.v ? d.v.gsub('~ap', '\x27') : '^');
                        // check if previous value must be used
                        valueCounter = 1;
                        while (cellValue == '^') {
                            prevd = eval('data.d' + (i + gbindex - (this.options.columnCount * valueCounter)));
                            cellValue = (prevd.v != null ? prevd.v : '^');
                            valueCounter++;
                        }


                        if (cellValue != oldgb) {
                            code += '<tr class="tgroupby"><td colspan=' + (this.options.columnCount) + '>' + gbcaption + ': ' + cellValue;
                            code += '<img class="clickme" onclick="' + elname + '.setGroupBy(\'' + gb + '\');" title="Remove grouping" src="icons/ungroupby.png" alt="Group by"/>';
                            code += '</td></tr>';
                            oldgb = cellValue;
                        }
                    }
                    code += '<tr class="tdata">';
                }

                // get data
                d = eval('data.d' + i);
                if (d == null)
                    break;

                // get column info from columns data
                currentColumn = i % this.options.columnCount - 1;
                if (currentColumn == -1) {
                    currentColumn = this.options.columnCount - 1;
                }
                hint = this.columns[currentColumn].hint;
                columnType = this.columns[currentColumn].type;
                columnVerb = this.columns[currentColumn].verb;

                hlink = '';
                hlink2 = '';

                // add scripts for in-place editor
                if (this.columns[currentColumn].ce == '1') {
                    try {
                        this.editors.push(this.editors.editor = new IPEditorData(this.columns[currentColumn].e1, this.columns[currentColumn].e2, this.columns[currentColumn].e3, d.e4, 'cell' + elname + i));
                    }
                    catch (e) {
                        alert('Error.TableView.ShowData.PushEditor: ' + e.Message);
                    }
                    cellId = 'id="cell' + elname + i + '"';
                }
                else {
                    cellId = '';
                }


                if (d.ot_id == '0') {
                    otid = '\'\'';
                }
                else {
                    otid = d.ot_id;
                }


                if (columnType == 'hl') {    // hyperlink
                    hlink = '<span ' + (hint == '' ? '' : 'title="' + hint + '"') + ' class="clickable" onclick="getObjectResponse(' + d.hlink + ',' + otid + ',\'' + columnVerb + '\', \'' + (d.p1 ? d.p1 : '') + '\', \'' + (d.p2 ? d.p2 : '') + '\', \'' + this.element + '\');">';
                    hlink2 = '</span>';
                }


                if (columnType == 'text' || columnType == 'hl' || columnType == 'cu' || columnType == 'number') { // hyperlink, currency
                    cellValue = (d.v != null ? d.v.gsub('~ap', '\x27') : '^');

                    // if cell is empty and can be edited, display 'Click to edit'
                    if (cellValue == '' && d.canedit == '1') {
                        cellValue = 'Click to edit';
                        cellId += ' class="grayedit"';  // add a gray, italic style to Click to edit to distinguish from normal data
                    }

                    if (columnType == 'cu' && cellValue == '') {
                        cellValue = '0.00';
                    }

                    if (columnType == 'number' && cellValue == '') {
                        cellValue = '0';
                    }


                    // check if previous value must be used
                    valueCounter = 1;
                    while (cellValue == '^') {
                        prevd = eval('data.d' + (i - (this.options.columnCount * valueCounter)));
                        cellValue = (prevd.v != null ? prevd.v : '^');
                        valueCounter++;
                    }


                    todisplay = '<span ' + cellId + ' >' + cellValue + '</span>';
                }

                if (columnType == 'yesno') {
                    if (d.v == '1') {
                        todisplay = 'Yes';
                    }
                    else {
                        todisplay = '';
                    }
                }

                if (columnType == 'icon') {
                    todisplay = '<span title="' + hint + '" class="clickable tvicon ' + d.v + '" onclick="getObjectResponse(' + d.hlink + ',' + otid + ',\'' + columnVerb + '\', \'\', \'\', \'' + this.element + '\');">&nbsp;&nbsp&nbsp;&nbsp</span>';
                }


                if (columnType == 'check') {
                    todisplay = '<input type="checkbox" id="ch_' + d.hlink + '">';
                }

                code += '<td class="tcell' + (columnType == 'icon' ? ' smalltcell' : '') + (columnType == 'currency' || columnType == 'number' ? ' tv_currency' : '') + '">' + hlink + todisplay + hlink2 + '</td>';
                //}
                if (i % this.options.columnCount == 0) {
                    code += '</tr>';
                }
            }
        }
        code += '</tbody></table>';


        if (this.options.hasfooter == 'true') {
            // show footer with stats and page numbers
            code += '<div class="tfooter">';

            // first button
            code += '<img class="clickme tvicon" src="icons/first.png" title="First page" alt="First" onclick="' + this.element + '.setPage(1);" />';

            // previous button
            if (this.options.currentPage > 1) {
                code += '<img class="clickme tvicon" src="icons/previous.png" title="Previous page" alt="Previous" onclick="' + this.element + '.setPage(' + (this.options.currentPage - 1) + ');" />';
            }

            // page selector combo
            code += 'Page <select class="" onchange="' + this.element + '.setPage(this.value);">';
            var itemsPerPage = [10, 20, 50, 100];

            for (var i = 1; i <= this.options.numOfPages; i++) {

                if (this.options.currentPage == i) {
                    sel = 'selected="selected"';
                }
                else {
                    sel = '';
                }
                code += '<option ' + sel + ' value="' + i + '">' + i + '</option>';
            };
            code += '</select> of ' + this.options.numOfPages + ' (' + this.options.numOfItems + ' items)';

            // next button
            if (this.options.currentPage < this.options.numOfPages) {
                code += '<img class="clickme tvicon" src="icons/next.png" title="Next page" alt="Next" onclick="' + this.element + '.setPage(' + (this.options.currentPage + 1) + ');" />';
            }

            // last button
            code += '<img class="clickme tvicon" src="icons/last.png" title="Last page" alt="Last" onclick="' + this.element + '.setPage(' + this.options.numOfPages + ');" />';


            // refresh button
            code += '<img class="clickme tvicon" src="icons/refresh.png" title="Refresh table" alt="Refresh" onclick="' + this.element + '.catchFilter();" />';


            // export button
            code += '<img class="clickme tvicon" src="icons/excel.png" title="Export data" alt="Export" onclick="' + this.element + '.requestExport();" />';


            // add combo for items per page
            code += '<select class="floatright" id="' + elname + '_npp" onchange="' + this.element + '.setNumberPerPage(\'' + elname + '_npp\');">';
            var itemsPerPage = [10, 20, 50, 100];

            itemsPerPage.each(function (item) {
                if (this.options.rowsPerPage == item) {
                    sel = 'selected="selected"';
                }
                else {
                    sel = '';
                }
                code += '<option ' + sel + ' value="' + item + '">Show ' + item + ' items</option>';
            }, this);

            code += '</select>';
            code += '</div>';
        }


        // insert the table data into the dom, replacing previous data
        $(this.target).innerHTML = code;
        if (script != '') {
            eval(script);
        }


        // run startup scripts to create in-place editors
        try {
            this.editors.each(function (c) {
                c.editor = new Ajax.InPlaceEditor(c.element, c.getParameters());
            }, this);
        }
        catch (e) {
            alert('Error.TableView.CreateInPlaceEditors: ' + e.Message);
        }


        // add tooltips
        SetTooltips('#' + this.target + ' span.clickable');
        SetTooltips('#' + this.target + ' img.clickme');


        // add refresh if needed
        if (this.options.refresh != 0 && this.refresher == null) {
            this.refresher = new PeriodicalExecuter(this.catchFilter.bindAsEventListener(this), this.options.refresh);  // remove stuck tooltips
        }

        // add event listeners for filter boxes
        this.columns.each(function (c) {
            if (c.canfilter == 'True') {
                if (c.combodata == null && c.autofilterqry == '') {
                    new Form.Element.DelayedObserver(elname + '_' + c.colname, 1.5, this.catchFilter.bindAsEventListener(this));
                }
            }
        }, this);
    },


    // a column sort header was clicked, refresh table data
    setSortBy: function (desc) {
        if (this.options.sortby == desc) {
            this.options.sortby += ' desc';
        }
        else {
            this.options.sortby = desc;
        }
        this.catchFilter();
    },


    // a column group by was clicked, refresh data
    setGroupBy: function (desc) {
        if (this.options.groupby == desc) {
            this.options.groupby = '';
        }
        else {
            this.options.groupby = desc;
        }

        this.catchFilter();
    },


    // the number of items to show per page was changed, refresh table data
    setNumberPerPage: function (el) {
        this.options.rowsPerPage = $(el).value;
        this.catchFilter();
    },


    // the page number was changed, refresh table data
    setPage: function (page) {
        this.options.currentPage = page;
        this.catchFilter();
    },


    // text was typed into one of the column filters, refresh table data
    catchFilter: function (el, id) {
        var elname = this.element;
        this.columns.each(function (c) {
            if (c.canfilter == 'True') {
                c.filterText = $F(elname + '_' + c.colname);
            }
        });

        this.requestData(); // update the table data
    },


    // catch auto filter
    // function must be set up like this, since li parameter is empty if the specified function call in the autcompleter is bound to an instance's function
    catchAutoFilter: function (text, li) {
        var ccid = text.id.gsub('auto_', '');

        $$('#choices_' + ccid + ' li.selected').each(function (c) {
            $(ccid).value = c.id + '*' + text.value;
        });

        this.catchFilter();
    },


    clearAutoFilter: function (filter) {
        $(filter).value = '0';

        this.catchFilter();
    },


    showNumberFilter: function (filter) {

        var f = new NumberFilter(filter);
        f.showFilter();

    },


    catchNumberFilter: function () {

        this.catchFilter();
    },


    stopListeners: function () {
        if (this.refresher != null) {
            this.refresher.stop();
            this.refresher = null;
        }

    }
};


//var NumberFilter = Class.create();

//NumberFilter.prototype = {
//    initialize: function (element, options) {
//        this.element = element;

//        this.options = {
//            obid: 0
//        };

//        Object.extend(this.options, options || {});
//    },

//    showFilter: function () {
//        var div1 = new Element('div', { 'id': 'div_' + this.element });
//        $('loc_' + this.element).insert(div1);


//        //code += '<div><select><option value="eq">=</option><option value="lt">\x3C</option><option value="gt">\x3E</option></select><input type="text" style="width:65px;" /></div>';
//        //code += '<div id="andor_' + this.element + '">';
//        //code += '<input type="button" value="and" onclick="$(\'andor_' + this.element + '\').insert({ before: \'<div>and<select></select><input type="text" style="width:65px;" /></div>\'});">';
//        //code += '<input type="button" value="or"></div>';


//        div1.insert(new Element('input', { 'type': 'button', 'value': 'and' }));
//        div1.insert(new Element('input', { 'type': 'button', 'value': 'or' }));

//        div1.insert(new Element('input', { 'type': 'button', 'value': 'Ok' }));
//        div1.insert(new Element('input', { 'type': 'button', 'value': 'Clear' }));
//    },


//    addFilterLine: function (type, target) {
//        var div1 = new Element('div');
//        var select1 = new Element('select');
//        select1.insert(new Element('option', { 'value': 'lt' }).update('x3C'));
//        select1.insert(new Element('option', { 'value': 'eq' }).update('='));
//        select1.insert(new Element('option', { 'value': 'gt' }).update('x3E'));

//        div1.insert(new Element('span').update(type));
//        div1.insert(select1);
//        div1.insert(new Element('input', { 'type': 'text', 'style': 'width:65px;' }));

//        $(target)insert( { 'before': div1});
//    }
//};
