﻿/// <reference name="MicrosoftAjax.js"/>

Type.registerNamespace("WebControls");

WebControls.TableView = function(element) {
    WebControls.TableView.initializeBase(this, [element]);

    this._trElements;
    this._items = null;
    this._selectedItem = null;
    this._currentEditRowIndex = null;
}

WebControls.TableView.prototype = {
    initialize: function() {
        WebControls.TableView.callBaseMethod(this, 'initialize');

        var that = this;
        
        
    },
    dispose: function() {
        //Add custom dispose actions here
        WebControls.TableView.callBaseMethod(this, 'dispose');
    },

    set_itemList: function(itemList) {

        var that = this;

        // Clear the internal reference variables        
        this._items = {};
        this._trElements = {};

        var table = this._tableEl;
        // Clear the table (remove all rows except header)
        while (table.rows.length > 1) {
            table.deleteRow(1);
        }

        var endRow = -1;

        if (itemList.length > 0) {
            // Set up a row for each item
            for (var i = 0; i < itemList.length; i++) {

                var item = itemList[i];                
                var rowIndex = i + 1;
                // Store reference to the item                
                this._items[rowIndex] = item;
                
                var itemTr = table.insertRow(-1); // -1 = append as last row                
                this._trElements[rowIndex] = itemTr;

                this.generateViewRow(rowIndex);
            }
        }
        else {
        }

    },
    
    _editButtonClicked: function(rowIndex) {    
        this._resetRows();
        this.generateEditRow(rowIndex);    
    },

    _deleteButtonClicked: function(rowIndex) {    
        this.generateDeleteConfirmRow(rowIndex);    
    },

    _saveButtonClicked: function(rowIndex) {    
        var item = this._items[rowIndex];

        var oldItem = this._items[rowIndex];
        var newItem = cloneObject(oldItem);
        
        var valid = true;
        for(var i in this._editControls) {
            if (! this._editControls[i].validate()) {
                valid = false;
                break;
            }
            newItem[i] = this._editControls[i].get_value();        
        }

        // I think we should only raise the event if
        // validation passes
        // var valid = this.validateControls();
        if (valid) {
            this._raiseEvent('itemSave', { oldItem: oldItem, item: newItem, rowIndex: rowIndex });
            
            // DO WE NEED THIS...?
            // this._resetRows();
        } else {
            alert("One or more fields is invalid");
        }
        
    },
    
    _deleteYesButtonClicked: function(rowIndex) {  
        var item = this._items[rowIndex];
        
        this._raiseEvent('itemDelete', { item: item, rowIndex: rowIndex });
        
        this._resetRows();
    },
    
    // This can be used for cancelling both edit and delete
    _cancelButtonClicked: function(rowIndex) {
        // this.generateViewRow(rowIndex);
        this._resetRows();
    },
    
//    _blinkRow: function(rowIndex) {
//        var tr = this._trElements[rowIndex];
//        tr.className = "scheduleGridRowHighlighted";
//        setTimeout(function() { tr.className = "scheduleGridRow"; }, 800);
//    },

    _clearTr: function(tr) {
        while (tr.cells.length > 0) {
            // This is in case some of the cells have been hidden...
            tr.cells[0].style.display = 'inline';
            tr.deleteCell(0);
        }
    },
    
    // This is used to reset all rows to their view state
    // (ie leave edit mode)
    _resetRows: function() {
    
        // Clear the edit control CCs
        for (var i in this._editControls) {
            this._editControls[i].dispose();   
        }
    
        if (this._currentEditRowIndex == 0) {
            this._removeAddRow();
        }
        if (this._currentEditRowIndex > 0) {
            this.generateViewRow(this._currentEditRowIndex);
        }
        this._currentEditRowIndex = null;
    },
    
    setupNewItem: function() {
    
        if (this._itemClass) {
            var newItem;
            newItem = eval("new " + this._itemClass + "()");
            if (this._foreignFieldName) {
                if (this._foreignID) {
                    newItem[this._foreignFieldName] = this._foreignID;
                } else {
                    programError("A foreignFieldName but no foreignID was specified");
                }
            }
            this._resetRows();
            this._setupAddRow(newItem);

        } else {
            programError("No item class specified");
        }    
        
    },
    
    _setupAddRow: function(newItem) {
        var table = this._tableEl;
        // Insert a row after the header, but before the other rows
        var tr = table.insertRow(1);
        // Store the private variables
        this._items[0] = newItem;

        this._trElements[0] = tr;
        this._currentEditRowIndex = 0;
        this.generateEditRow(0);
    },

    _removeAddRow: function() {
        if (this._trElements[0]) {
            var table = this._tableEl;
            table.deleteRow(1);

            delete (this._items[0]);
            delete (this._trElements[0]);
        }
        this._currentEditRowIndex = null;
    },

    generateViewRow: function(rowIndex) {
    
        var that = this;
    
        var item = this._items[rowIndex];
        var itemTr = this._trElements[rowIndex];
        
        this._clearTr(itemTr);
    
        // If it's the currently selected item, highlight it
        // (Should only do this if we are allowing selection)
        if (this._allowSelection && this._selectedItem != null && item.ID == this._selectedItem.ID) {
            itemTr.className = this._selectedRowCssClass;
        } else {
            itemTr.className = this._rowCssClass;
        }
        // Attach references to use in the event handler                
        itemTr.gridObj = this;
        itemTr.rowIndexValue = rowIndex;  // can't use 'rowIndex' as a property
        if (this._allowSelection) {
            itemTr.onclick = function() {
                // Remember that in here, 'this' refers to the tr element
                this.gridObj.rowSelected(this.rowIndexValue);
            }
            itemTr.style.cursor = 'pointer';            
        }

        // This is driven by the config data
        var columns = this.get_columns();
        for (var c = 0; c < columns.length; c++) {
            var column = columns[c];

            var td = itemTr.insertCell(-1);  // -1 = append as last cell
            td.style.overflow = 'hidden';
            var value = null;
            if (column.FieldName) {
                value = item[column.FieldName];
            }

            switch (column.Type) {
                case "Numeric":
                    td.style.textAlign = "center";
                    td.innerHTML = value;
                    break;
                case "Date":
                    td.style.textAlign = "center";
                    td.innerHTML = formatDate(value);
                    break;
                case "File":
                    if (value) {
                        var url = this._downloadLinkBaseUrl + (this._downloadLinkBaseUrl.endsWith('/') ? '' : '/') + value;
                        td.innerHTML = "<a href=" + url + ">" + value + "</a>";
                    } else {
                    
                    }
                    break;
//                case "Image":
//                    var img = document.createElement("IMG");
//                    td.appendChild(img);
//                    var baseImageUrl = "http://www.nirvana.altpro.cyberdesignfactory.com/AltProStatic/nirvana/photos/";
//                    var imgCC = $create(WebControls.Image, {baseUrl: baseImageUrl}, {}, {}, img);
//                    imgCC.set_value(value);
//                    // td.style.textAlign = "center";
//                    // td.innerHTML = '<img src="" />'; // formatDate(value);
//                    break;
                case "LinkButton":
                    var e = { cancel: false, buttonName: column.ButtonName, item: item };
                    this._raiseEvent('showButton', e);
                    if (! e.cancel) {
                        td.style.textAlign = "center";
                        td.innerHTML = column.ButtonText;
                        td.buttonName = column.ButtonName;
                        td.itemID = item.ID;
                        td.item = item;
                        td.onclick = function() {
                            that._raiseEvent('buttonClicked', { id: this.itemID, item: item, buttonName: this.buttonName });
                        };
                        td.style.cursor = 'pointer';
                    }
                    break;
                case "Custom":
                    this._raiseEvent('generateCustomTd', { td: td, columnName: column.FieldName, item: item });
                    break;
                default:
                    var value2 = value;
                    if (column.MaxLength > 0) {
                        if (value && (value.length > column.MaxLength)) {
                            td.title = value;
                            value2 = value.substr(0, column.MaxLength);
                        }
                    }                
                    td.innerHTML = value2;
            }

            //                    if (column.Width) {
            //                        td.style.width = column.Width;
            //                    }

            // td.style.paddingLeft = column.paddingLeft;
            td.noWrap = true;
        }
        
        if (this._showStartEnd) {                                
            var toStartTd = itemTr.insertCell(-1);
            // Don't provide an toStart link for the first item
            if (item.Order > 1) {
                toStartTd.innerHTML = "Start";
                toStartTd.itemID = item.ID;  // Could make PK field configurable later
                toStartTd.onclick = function() {
                    that._raiseEvent('itemToStart', { id: this.itemID });
                };
            }                
            toStartTd.style.cursor = 'pointer';
        }
        
        if (this._showUpDown) {
            var upTd = itemTr.insertCell(-1);
            // Don't provide an up link for the first item
            if (item.Order > 1) {
                if (this._upArrowCssClass) {
                    upTd.className = this._upArrowCssClass;
                } else {
                    upTd.innerHTML = "Up";
                }
                upTd.itemID = item.ID;  // Could make PK field configurable later
                upTd.onclick = function() {
                    that._raiseEvent('itemUp', { id: this.itemID });
                };
                upTd.style.cursor = 'pointer';
            }
                        
            var downTd = itemTr.insertCell(-1);
            // Don't provide a down link for the last item
            // The itemCount property needs to be set by the caller
            if (item.Order < this._itemCount) {
                if (this._downArrowCssClass) {
                    downTd.className = this._downArrowCssClass;
                } else {
                    downTd.innerHTML = "Down";
                }                
                downTd.itemID = item.ID;  // Could make PK field configurable later
                downTd.onclick = function() {
                    that._raiseEvent('itemDown', { id: this.itemID });
                };
                downTd.style.cursor = 'pointer';
            }
        }
         
        if (this._showStartEnd) {                                    
            var toEndTd = itemTr.insertCell(-1);
            // Don't provide a toEnd link for the last item
            // The itemCount property needs to be set by the caller
            if (item.Order < this._itemCount) {
                toEndTd.innerHTML = "End";
                toEndTd.itemID = item.ID;  // Could make PK field configurable later
                toEndTd.onclick = function() {
                    that._raiseEvent('itemToEnd', { id: this.itemID });
                };
                toEndTd.style.cursor = 'pointer';
            }                    
        }
        
        if (this._allowEdit) {
            var editTd = itemTr.insertCell(-1);
            editTd.innerHTML = "Edit"; // FOR NOW
            editTd.rowIndex = rowIndex;
            editTd.itemID = item.ID;  // Could make PK field configurable later
            editTd.onclick = function() {
                // that._raiseEvent('itemEdit', { id: this.itemID });
                that._editButtonClicked(this.rowIndex);
            };
            editTd.style.cursor = 'pointer';            
        }

        if (this._allowDelete) {
            var deleteTd = itemTr.insertCell(-1);
            deleteTd.innerHTML = "Delete"; // FOR NOW
            deleteTd.rowIndex = rowIndex;
            deleteTd.itemID = item.ID;  // Could make PK field configurable later
            deleteTd.onclick = function() {
                // that._raiseEvent('itemEdit', { id: this.itemID });
                that._deleteButtonClicked(this.rowIndex);
            };
            deleteTd.style.cursor = 'pointer';            
        }
    
    },    

    generateEditRow: function(rowIndex) {
        var that = this;
        
        var item = this._items[rowIndex];
        var itemTr = this._trElements[rowIndex];
        itemTr.className = this._selectedRowCssClass;
    
//        // In case another row is being edited...
//        if (this._editRowIndex > 0) {
//            this._resetRows();
//        }
        
        this._clearTr(itemTr);
    
        this._currentEditRowIndex = rowIndex;

        this._editControls = {};

        // This is driven by the config data
        var columns = this.get_columns();
        for (var c = 0; c < columns.length; c++) {
            var column = columns[c];

            var td = itemTr.insertCell(-1);
            // Add a position:relative style so nested elements
            // (eg autocomplete tables) are positioned correctly
            // td.style.position = 'relative';
            
            var value = item[column.FieldName];

            cloneElement($get(this._editTemplatePanelIDs[column.FieldName]), td, item.ID);
            cloneElementCCs(
                $get(this._editTemplatePanelIDs[column.FieldName]),
                item.ID,
                null
            );
            // Set the value
            var editControl = $find(column.EditTemplateControlClientID + "_" + item.ID);
            this._editControls[column.FieldName] = editControl;
            editControl.set_value(value);

//            switch (column.Type) {
//                case "String":                
//                    var inputEl = document.createElement("INPUT");
//                    inputEl.type = "text";
//                    td.appendChild(inputEl);
//                    
//                    var input = $create(WebControls.TextInput, {}, {}, {}, inputEl);
//                    
//                    input.set_value(value);
//                    this._editControls[column.FieldName] = input;
//                    
//                    break;
//                case "Int32":
//                    var inputEl = document.createElement("INPUT");
//                    inputEl.type = "text";
//                    td.appendChild(inputEl);
//                    
//                    // THIS IS ACTUALLY THE ONLY LINE THAT IS DIFFERENT FROM 'String' CASE
//                    var input = $create(WebControls.NumericInput, {numElementsUpForValidationHighlight:2}, {}, {}, inputEl);

//                    input.set_value(value);
//                    this._editControls[column.FieldName] = input;                    
//                    
//                    break;
//                
//                default:
//                    // td.innerHTML = value;
//                    programError("Column Type " + column.Type + " not recognised");
//            }

            td.noWrap = true;
             
        }

        // Add spacing as necessary so columns line up...
        if (this._showStartEnd) {                                
            var toStartTd = itemTr.insertCell(-1);
        }
        if (this._showUpDown) {
            var upTd = itemTr.insertCell(-1);
            var downTd = itemTr.insertCell(-1);
        }         
        if (this._showStartEnd) {                                    
            var toEndTd = itemTr.insertCell(-1);
        }

        var saveTd = itemTr.insertCell(-1);
        saveTd.innerHTML = "Save"; // FOR NOW
        saveTd.rowIndex = rowIndex;
        saveTd.itemID = item.ID;  // Could make PK field configurable later
        saveTd.onclick = function() {
            that._saveButtonClicked(this.rowIndex);
        };
        saveTd.style.cursor = 'pointer';            

        var cancelTd = itemTr.insertCell(-1);
        cancelTd.innerHTML = "Cancel"; // FOR NOW
        cancelTd.rowIndex = rowIndex;
        cancelTd.itemID = item.ID;  // Could make PK field configurable later
        cancelTd.onclick = function() {
            that._cancelButtonClicked(this.rowIndex);
        };
        cancelTd.style.cursor = 'pointer';            
    
    },
    
    generateDeleteConfirmRow: function(rowIndex) {
        var that = this;
    
        // In case another row is being edited...
        this._resetRows();
    
        var item = this._items[rowIndex];
        var itemTr = this._trElements[rowIndex];
        itemTr.className = this._selectedRowCssClass;
        
        this._clearTr(itemTr);
    
        this._currentEditRowIndex = rowIndex;

        this._editControls = {};

//        var colSpan = 0;

//        // Determine the correct colspan
//        var columns = this.get_columns();
//        for (var c = 0; c < columns.length; c++) {
//            var column = columns[c];

//            if (column.showInViewMode == true && !this.isFieldDisabled(column.fieldName)) {
//                colSpan++;
//            }
//        }

        var colSpan = this.get_columns().length;

        var messageTd = itemTr.insertCell(-1);
        messageTd.colSpan = colSpan;
        messageTd.style.textAlign = 'center';
        messageTd.innerHTML = "Delete this item?";

        // Add spacing as necessary so columns line up...
        if (this._showStartEnd) {                                
            var toStartTd = itemTr.insertCell(-1);
        }
        if (this._showUpDown) {
            var upTd = itemTr.insertCell(-1);
            var downTd = itemTr.insertCell(-1);
        }         
        if (this._showStartEnd) {                                    
            var toEndTd = itemTr.insertCell(-1);
        }

        var deleteTd = itemTr.insertCell(-1);
        deleteTd.innerHTML = "Delete"; // FOR NOW
        deleteTd.rowIndex = rowIndex;
        deleteTd.itemID = item.ID;  // Could make PK field configurable later
        deleteTd.onclick = function() {
            that._deleteYesButtonClicked(this.rowIndex);
        };
        deleteTd.style.cursor = 'pointer';            

        var cancelTd = itemTr.insertCell(-1);
        cancelTd.innerHTML = "Cancel"; // FOR NOW
        cancelTd.rowIndex = rowIndex;
        cancelTd.itemID = item.ID;  // Could make PK field configurable later
        cancelTd.onclick = function() {
            that._cancelButtonClicked(this.rowIndex);
        };
        cancelTd.style.cursor = 'pointer';            
        
    },

    get_selectedItem: function() {
        return this._selectedItem;
    },

    get_selectedID: function() {
        if (this._selectedItem) {
            return this._selectedItem.ID;
        } else {
            return null;
        }
    },

    set_selectedID: function(id) {
        if (id == null) {
            this._selectedItem = null;
            this.highlightRow(null);
        } else {
            // Look for the ID in the grid
            var index = null;
            // for (var i = 1; i <= 10; i++) {
            for (var i in this._items) {
                if (this._items[i] && (this._items[i].ID == id)) {
                    index = i;
                }
            }
            if (index == null) {
                alert("ID " + id + " not found in grid");  // THIS WAS COMMENTED OUT
            } else {
                this._selectedItem = this._items[index];
                this.highlightRow(index);
            }
        }
    },

    rowSelected: function(index) {

        this.highlightRow(index);

        var selectedItem = this._items[index];

        // Store a copy of the selected item
        this._selectedItem = selectedItem;

        // this._raiseEvent('itemClicked', { item: this._items[index] });
        this._raiseEvent('itemClicked', { id: selectedItem.ID, item: selectedItem });
    },

    highlightRow: function(index) {
        var table = this._tableEl;
        var rows = table.rows;
        // Note this starts from one to avoid clearing header row
        for (var i = 1; i < rows.length; i++) {
            var row = rows[i];
            row.className = this._rowCssClass;
        }
        if (index != null) {
            table.rows[index].className = this._selectedRowCssClass;
        }
    },

    deselectRow: function() {
        this._selectedItem = null;
        this.highlightRow(null);
    }

}
WebControls.TableView.createProperty("tableEl");
WebControls.TableView.createProperty("columns");
WebControls.TableView.createProperty("rowCssClass");
WebControls.TableView.createProperty("selectedRowCssClass");
WebControls.TableView.createProperty("upArrowCssClass");
WebControls.TableView.createProperty("downArrowCssClass");
WebControls.TableView.createProperty("itemClass");
WebControls.TableView.createProperty("foreignID");
WebControls.TableView.createProperty("foreignFieldName");
WebControls.TableView.createProperty("showUpDown");
WebControls.TableView.createProperty("showStartEnd");
WebControls.TableView.createProperty("allowSelection");
WebControls.TableView.createProperty("allowAdd");
WebControls.TableView.createProperty("allowEdit");
WebControls.TableView.createProperty("allowDelete");
// WebControls.TableView.createProperty("editControlRowEl");
WebControls.TableView.createProperty("editTemplatePanelIDs");
WebControls.TableView.createProperty("downloadLinkBaseUrl");
// This is used to determine whether to provide the down/toEnd links for
// ordered lists.  It is the TOTAL rows in the list (not just in this page)
// Because otherwise the TableView has no way of knowing whether to provide
// the links or not
WebControls.TableView.createProperty("itemCount");

WebControls.TableView.createEvent("itemClicked");
WebControls.TableView.createEvent("itemToStart");
WebControls.TableView.createEvent("itemUp");
WebControls.TableView.createEvent("itemDown");
WebControls.TableView.createEvent("itemToEnd");
WebControls.TableView.createEvent("itemEdit");
WebControls.TableView.createEvent("itemSave");
WebControls.TableView.createEvent("itemDelete");  // Probably only need to have this for when delete is confirmed
WebControls.TableView.createEvent("showButton");
WebControls.TableView.createEvent("buttonClicked");
WebControls.TableView.createEvent("generateCustomTd");
WebControls.TableView.createEvent("itemSaved");

WebControls.TableView.registerClass('WebControls.TableView', Sys.UI.Control);

if (typeof (Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();

if(typeof(Sys)!=='undefined')Sys.Application.notifyScriptLoaded();