﻿/// <reference name="MicrosoftAjax.js"/>

Type.registerNamespace("WebControls");

WebControls.ListView = function(element) {
    WebControls.ListView.initializeBase(this, [element]);

    this._eventRegister = {};
    this._foreignID = null;
    this._items = {};
    this._itemsByID = {};
    this._itemDivs = {};
    this._formViews = {};
}

WebControls.ListView.prototype = {
    initialize: function() {
        WebControls.ListView.callBaseMethod(this, 'initialize');

        var that = this;

        if (this._dataSource) { 
            if (this._loadOnInit) {
                this.loadList();
            }
            
            this.add_itemSave(
                function(sender, e) {
                    that._dataSource.saveItem(
                        e.item,
                        function(result) {
                            // alert("saved");
                            that.loadList();
                        }
                    );
                }
            );
            
            this.add_itemDelete(
                function(sender, e) {
                    that._dataSource.deleteItem(
                        e.item,
                        function(result) {
                            that.loadList();
                        }
                    );
                }
            );            
        }
        
        if (this._addButton) {
            this._addButton.add_buttonClicked(
                function(sender, e) {
                    that.setupNewItem();
                }
            );
        }
        
        this.showMain();
        
    },
    dispose: function() {
        //Add custom dispose actions here
        WebControls.ListView.callBaseMethod(this, 'dispose');
    },
    
    showLoading: function() {
        this._panelSet.showPanel(this._loadingPanelID);
    },
    showMain: function() {
        this._panelSet.showPanel(this._mainPanelID);
    },
    
    loadList: function() {
        var that = this;
        if (this._dataSource) {
        
            if (this._showLoadingPanel) {
                this.showLoading();
            }
        
            this._dataSource.getListByForeignID(
                this._foreignID,
                null,  // filter
                function(itemList) {
                    that.set_itemList(itemList);
                    var firstItemID = null;
                    if (itemList.length > 0) { firstItemID = itemList[0].ID; }
                    that._raiseEvent('listLoaded', {firstItemID: firstItemID, itemCount: itemList.length});
                }
            );
        } else {
            programError("No datasource");
        }    
    },
    
    add_eventHandler: function(controlID, eventName, handlerFunction) {
        
        var thisID = this.get_id();
        var i = thisID.lastIndexOf('_');
        var prefix = (i > -1) ? thisID.substr(0, i + 1) : '';

        var controlClientID = prefix + controlID;
        
        if (! this._eventRegister[controlClientID]) {
            this._eventRegister[controlClientID] = {};
        }
        
        this._eventRegister[controlClientID][eventName] = handlerFunction;        
    },
    
    _reloadList : function() {
        this.set_itemList(this._itemList);
    },
    set_itemList: function(itemList) {
        var that = this;

        // Store item list in case we need to reload it
        this._itemList = itemList;
        
        // Clear the internal reference variables        
        this._items = {};
        this._itemsByID = {};
        this._itemDivs = {};
        
        this._formViews = {};

        var holdingDiv = this._holdingDiv;
        // Clear the item divs
        var x = document.createElement("DIV");
        //x.childNodes.l
        while (holdingDiv.childNodes.length > 0) {
        
            // *********************************** NOT SURE IF THIS IS GOING TO WORK ************************************
            disposeElementCCs(holdingDiv.childNodes[0]);
            // *********************************** NOT SURE IF THIS IS GOING TO WORK ************************************
        
            holdingDiv.removeChild(holdingDiv.childNodes[0]);
        }

        // 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;
                
                // Store a reference by id as well
                this._itemsByID[item.ID] = item;
                
                var itemDiv = document.createElement("DIV");
                holdingDiv.appendChild(itemDiv);
                itemDiv.className = this._itemDivCssClass;
                this._itemDivs[rowIndex] = itemDiv;

                this.generateItemFormView(rowIndex);
            }
        }
        else {
        }
        
        if (this._addButton) {
            this._addButton.show();
        }
        
        this.showMain();
    },
    
    // I think we will have generateViewRow etc
    // same as the TableView, and it will just
    // have to generate the copy of the FormView
    // and put it in the appropriate mode.
    // (so maybe it will be factored to have a
    // common routine to set up the formview)
    
    _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() {
        if (this._currentEditRowIndex == 0) {
            this._removeAddRow();
        }
        if (this._currentEditRowIndex > 0) {
            // this.generateViewRow(this._currentEditRowIndex);
            this._formViews[this._currentEditRowIndex].showDefaultView();
        }
        this._currentEditRowIndex = null;                       
        
        if (this._addButton) {
            this._addButton.show();
        }
    },
    
    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._raiseEvent("constructingNewItem", {item: newItem});
            this._resetRows();
            this._setupAddRow(newItem);

        } else {
            programError("No item class specified");
        }    
        
    },
    
    _setupAddRow: function(newItem) {
        var holdingDiv = this._holdingDiv;
        var itemDiv = document.createElement("DIV");
        
        holdingDiv.appendChild(itemDiv);
        itemDiv.className = this._itemDivCssClass;
        this._items[0] = newItem;
        this._itemDivs[0] = itemDiv;        
        this._currentEditRowIndex = 0;        
                
        this.generateItemFormView(0);
        
        if (this._addButton) {
            this._addButton.hide();
        }
    },

    _removeAddRow: function() {
        if (this._itemDivs[0]) {
            disposeElementCCs(this._itemDivs[0]);
            this._holdingDiv.removeChild(this._itemDivs[0]);

            delete (this._items[0]);
            delete (this._itemDivs[0]);
        }
        this._currentEditRowIndex = null;
    },
        
    generateItemFormView: function(rowIndex) {

        var that = this;
    
        var item = this._items[rowIndex];
        var itemDiv = this._itemDivs[rowIndex];
        
        // This will be 0 if we're adding a new item
        var itemID = (item.ID > 0) ? item.ID : 0;
        
        // DO WE NEED THE EQUIVALENT OF THIS???????????????
        // this._clearTr(itemTr);
        
        // var td = itemTr.insertCell(-1);
        // td.className = this._tableCellCssClass;
        
        // Only do this if it's not an 'add' row
        if (this._allowSelection && itemID > 0) {
            itemDiv.style.cursor = 'pointer';
            itemDiv.itemID = itemID;
            itemDiv.onclick = function() {
                that._raiseEvent('itemClicked', { id: this.itemID});
            };
        }
        
        var templatePanelSet = this._templateFormView.get_panelSet();
        var templateDisplayPanelIDs = templatePanelSet.get_displayPanelIDs();
        var displayPanelIDs = {};
        for (var d in templateDisplayPanelIDs) {
            var templateDisplayPanelID = templateDisplayPanelIDs[d];
            // ** Do we need to use a different value for d? **
            var displayPanelID = templateDisplayPanelID + "_" + itemID;
            displayPanelIDs[d] = displayPanelID;
            // var div = document.createElement("DIV");
            // div.id = displayPanelID;
            // this.cloneElement($get(templateDisplayPanelID), div, itemID);
            cloneElement($get(templateDisplayPanelID), itemDiv, itemID);
            
            // Here, we can specify a custom function to act on each CC...
            cloneElementCCs(
                $get(templateDisplayPanelID),
                itemID,
                function(newCC, referenceEl) {

                    // If any events have been registered, set up the appropriate handler
                    if (that._eventRegister[referenceEl.id]) {
                        var item = that._itemsByID[itemID];
                        for (var e in that._eventRegister[referenceEl.id]) {
                            var eventName = e;
                            var handlerFn = that._eventRegister[referenceEl.id][e];
                            newCC.get_events().addHandler(
                                eventName,
                                function(sender, e) {
                                    handlerFn(sender, e, item);
                                }
                            );                    
                        }
                    }                    
                }
             );

        }
        var panelSetSpan = document.createElement("SPAN");
        itemDiv.appendChild(panelSetSpan);
        var panelSet = $create(WebControls.PanelSet, { displayPanelIDs: displayPanelIDs }, {}, {}, panelSetSpan);
        
/////////////////////// NO NEED FOR THIS        panelSet.showPanel(this._templateFormView.get_viewPanelID());
        
        // For formview, basically need to set up fields, panelSet and view/edit/dc panel ids
        // for the fields, we just need to adjust the view/edit/dccontrolids (appending _item.ID)
        
        var templateFields = this._templateFormView.get_fields();
        var fields = [];
        for(var f = 0; f < templateFields.length; f++) {
            var templateField = templateFields[f];
            var field = {};
            field.FieldName = templateField.FieldName;
            field.ViewControlID = templateField.ViewControlID ? templateField.ViewControlID + "_" + itemID : null;
            field.EditControlID = templateField.EditControlID ? templateField.EditControlID + "_" + itemID : null;
            field.DeleteConfirmControlID = templateField.DeleteConfirmControlID ? templateField.DeleteConfirmControlID + "_" + itemID : null;
            fields.push(field);
        }
        var formViewSpan = document.createElement("SPAN");           
        itemDiv.appendChild(formViewSpan);
        var formView =
            $create(
                WebControls.FormView,
                {
                    // id: this._templateFormView.get_id() + "_" + item.ID,
                    fields: fields,
                    panelSet: panelSet,
                    
                    editButton: this._templateFormView.get_editButton()
                              ? $find(this._templateFormView.get_editButton().get_id() + "_" + itemID)
                              : null,
                    deleteButton: this._templateFormView.get_deleteButton()
                              ? $find(this._templateFormView.get_deleteButton().get_id() + "_" + itemID)
                              : null,
                    saveButton: this._templateFormView.get_saveButton()
                              ? $find(this._templateFormView.get_saveButton().get_id() + "_" + itemID)
                              : null,
                    cancelButton: this._templateFormView.get_cancelButton()
                              ? $find(this._templateFormView.get_cancelButton().get_id() + "_" + itemID)
                              : null,
                    deleteYesButton: this._templateFormView.get_deleteYesButton()
                              ? $find(this._templateFormView.get_deleteYesButton().get_id() + "_" + itemID)
                              : null,
                    deleteNoButton: this._templateFormView.get_deleteNoButton()
                              ? $find(this._templateFormView.get_deleteNoButton().get_id() + "_" + itemID)
                              : null,
                    
                    viewPanelID: this._templateFormView.get_viewPanelID(),
                    editPanelID: this._templateFormView.get_editPanelID(),
                    deleteConfirmPanelID: this._templateFormView.get_deleteConfirmPanelID()
                },
                {},
                {},
                formViewSpan
            );
        formView.add_itemSave(
            function(sender, e) {
                // Might possibly need to add extra parameters
                // to e later
                that._raiseEvent("itemSave", e);
            }
        );
        formView.add_itemDelete(
            function(sender, e) {
                // Might possibly need to add extra parameters
                // to e later
                that._raiseEvent("itemDelete", e);
            }
        );
        
        formView.add_editClicked(
            function(sender, e) {
                that._resetRows();
                that._currentEditRowIndex = rowIndex;
            }
        );
        
        formView.add_cancelClicked(
            function(sender, e) {
                // Need to remove the formView
                // here if it's an add row and cancel is clicked
                // Also need to make sure once item is saved that
                // this then doesn't happen (maybe won't if list
                // has been reloaded)
                // (Maybe easiest way is just to reload the list)
                if (! (e.item.ID > 0)) {
                    that._resetRows();         
                    // **** WAS RELOADING LIST HERE ****
                    // that._reloadList();
                }

            }
        );

        // formView.set_id(this._templateFormView.get_id() + "_" + item.ID);
        formView.set_item(item);
        // Start off in edit mode if we're adding a new item
        if (! item.ID > 0) {
            formView.showEdit();
        }
        
        this._formViews[rowIndex] = formView;
        
    },
    
//    // May be possible to simplify this using 'referenceEl.cloneNode()'    
//    cloneElement: function(referenceEl, parentEl, newID) {
//        var nodeName = referenceEl.nodeName;
//        // Don't try to copy '#text' etc
//        if (nodeName.indexOf('#') == -1) {            
//            // Clear any event handlers on the reference element before copying (** THIS WAS THE KEY **)
//            $clearHandlers(referenceEl);

//            var newEl = referenceEl.cloneNode(false);
//            // var newEl = $(referenceEl).clone(true).get(0);
//            if (referenceEl.id) {
//                newEl.id = referenceEl.id + "_" + newID;        
//            }
//            // Remove any associated CC
//            if (newEl.control) {
//                // delete newEl.control;
//                newEl.control = undefined;
//            }
//            
//            parentEl.appendChild(newEl);
//            
//            // Recursive call
//            for(var i = 0; i < referenceEl.childNodes.length; i++) {
//                this.cloneElement(referenceEl.childNodes[i], newEl, newID);
//            }
//        } else {
//        
//            // If it's #text etc, copy the node value
//        
//            // var newEl = document.createElement(nodeName);
//            // newEl.nodeValue = referenceEl.nodeValue;
//            var newEl = referenceEl.cloneNode(false);
//            parentEl.appendChild(newEl);
//        
//            // debugger;
//        }
//        
//    },

//    // May be possible to simplify this using 'referenceEl.cloneNode()'    
//    cloneElementCCs: function(referenceEl, newID, customFn) {
//        var nodeName = referenceEl.nodeName;
//        
//       /*
//        Here, we are going to need to recurse down through the elements.
//        Should this be down through the reference elements or the new
//        elements.
//        Perhaps it's okay to go down through the reference elements
//        because when we find an element which has a CC, it must
//        have an id, so we can at that point work out what the id of
//        the new element must be and find it.
//        
//        */

//        // Should look for an attached client component and clone here
//        if (referenceEl.id && $find(referenceEl.id)) {
//            var referenceCC = $find(referenceEl.id);
//            var refType = Object.getType(referenceCC);
//            
//            var newEl = $get(referenceEl.id + "_" + newID);
//            
//            // Need to create the control 'manually'
//            // so we can copy properties before initialising
//            // (or we could put them in an array, but I think
//            // this is easier)
//            // $create(refType, {}, {}, {}, newEl);
//            // var newCC = $find(newEl.id);

//            var newCC = new refType(newEl);  // Manual $create
//            // Copy any properties that are not currently defined across
//            // (except events)
//            for(var ccp in referenceCC) {                              // Check it has a value
//                if (typeof(newCC[ccp]) == 'undefined' && ccp != '_events' && referenceCC[ccp]) {
//                                
//                    // If it's an element reference, resolve to the
//                    // correct cloned element
//                    if (referenceCC[ccp].nodeName) {  // IS HTML ELEMENT
//                        newCC[ccp] = $get(referenceCC[ccp].id + "_" + newID);   // V------ Not sure why this check doesn't work
//                    } else if (referenceCC[ccp]._element) { // instanceof Sys.Component) // IS COMPONENT PROPERTY
//                        // Set the reference to the component in the item instance
//                        newCC[ccp] = $find(referenceCC[ccp].get_id() + "_" + newID);
//                    } else {
//                        newCC[ccp] = referenceCC[ccp];
//                    }                    
//                }
//            }
//            newCC.initialize();  // Manual $create
//            Sys.Application.addComponent(newCC);  // Manual $create
//            
//            // If a custom function has been provided, use it            
//            if (customFn) {
//                customFn(newCC, referenceEl);
//            }            
//                        
//        }
//            
//        // Recursive call
//        for(var i = 0; i < referenceEl.childNodes.length; i++) {
//            this.cloneElementCCs(referenceEl.childNodes[i], newID, customFn);
//        }
//        
//    },
//        
//    disposeElementCCs: function(element) {
//        // alert("disposing a " + element.nodeName + (element.id ? (' (' + element.id + ')') : '') );
//        if (element.id && $find(element.id)) {
//            var elId = element.id;
//            // debugger;
//            $find(element.id).dispose();
//        }
//    
//        // Recursive call
//        for(var i = 0; i < element.childNodes.length; i++) {
//            // this.cloneElement(referenceEl.childNodes[i], newEl, newID);
//            this.disposeElementCCs(element.childNodes[i]);
//        }
//    },

    get_foreignID: function() {
        return this._foreignID;
    },    
    set_foreignID: function(value) {
        this._foreignID = value;
        if (this._dataSource) {
            this._dataSource.set_foreignID(value);
        }
    }    

}
WebControls.ListView.createProperty("panelSet");
WebControls.ListView.createProperty("loadingPanelID");
WebControls.ListView.createProperty("mainPanelID");
WebControls.ListView.createProperty("templateDiv");
WebControls.ListView.createProperty("templateFormView");
WebControls.ListView.createProperty("holdingDiv");
WebControls.ListView.createProperty("holdingDivCssClass");
WebControls.ListView.createProperty("itemDivCssClass");
WebControls.ListView.createProperty("itemClass");
WebControls.ListView.createProperty("foreignFieldName");
WebControls.ListView.createProperty("addButton");
WebControls.ListView.createProperty("loadOnInit");
WebControls.ListView.createProperty("dataSource");
WebControls.ListView.createProperty("allowSelection");
WebControls.ListView.createProperty("columns");
WebControls.ListView.createProperty("showLoadingPanel");

WebControls.ListView.createEvent("itemClicked");
WebControls.ListView.createEvent("itemSave");
WebControls.ListView.createEvent("itemDelete");
WebControls.ListView.createEvent("listLoaded");
WebControls.ListView.createEvent("constructingNewItem");

WebControls.ListView.registerClass('WebControls.ListView', Sys.UI.Control);

if (typeof (Sys) !== 'undefined') Sys.Application.notifyScriptLoaded();

if(typeof(Sys)!=='undefined')Sys.Application.notifyScriptLoaded();