Ext.ns('InnateImmunity');

InnateImmunity.ExonExpressionVisualization = function() {

    // private variables
    var rootComponent = null;
    var sampleSelectInstance = null;

    var geneListStore = new Ext.data.ArrayStore({
        fields: [
            {name: 'displayName', type: 'string'},
            {name: 'ensemblGeneId', type: 'int'},
            {name: 'start', type: 'int'},
            {name: 'stop', type: 'int'},
            {name: 'strand', type: 'int'},
            {name: 'chromosomeName', type: 'string'},
            {name: 'exonViewLink', type: 'string'}
        ]
    });
    var GeneListRecord = Ext.data.Record.create(
    {name: 'displayName'},
    {name: 'ensemblGeneId'},
    {name: 'start'},
    {name: 'stop'},
    {name: 'strand'},
    {name: 'chromosomeName'},
    {name: 'exonViewLink'});

    var searchResultStore = new Ext.data.ArrayStore({
        fields: [
            {name: 'displayName', type: 'string'},
            {name: 'ensemblGeneId', type: 'int'},
            {name: 'start', type: 'int'},
            {name: 'stop', type: 'int'},
            {name: 'strand', type: 'int'},
            {name: 'chromosomeName', type: 'string'}
        ]
    });
    var SearchGeneRecord = Ext.data.Record.create(
    {name: 'displayName'},
    {name: 'ensemblGeneId'},
    {name: 'start'},
    {name: 'stop'},
    {name: 'strand'},
    {name: 'chromosomeName'});

    // ----------------------------------------------------------------------------------------------------------------
    // private methods
    //

    // load up gene list add window
    function onAddGeneList() {

        var geneListSearchForm = new Ext.form.FormPanel({
            xtype:"form",
            border: false,
            buttons: [{
                text: "Add Genes",
                handler: function() {
                    if (Ext.getCmp("enteredGeneList").getValue() !== "") {
                        searchForGeneList(Ext.getCmp("enteredGeneList").getValue());
                    }
                    win.close();
                }
            },{
                text: "Close",
                handler: function() {
                    win.close();
                }
            }],
            items:[{
                xtype:"fieldset",
                title:"Gene Names",
                autoHeight:true,
                items:[{
                    height: 200,
                    xtype:"textarea",
                    fieldLabel:"One per line",
                    name:"enteredGeneList",
                    id:"enteredGeneList"
                }]
            }]
        });

        var win = new Ext.Window({
            id: "addListWindow",
            title: "Add List of Genes",
            modal: true,
            width: 250,
            height: 325,
            items: [
                geneListSearchForm
            ]
        });
        win.show();
    }

    // loads up the search form in a window
    function onAddGene() {
        // search form
        var geneSearchForm = new Ext.form.FormPanel({
            xtype:"form",
            border: false,
            buttons: [{
                text: "Search",
                handler: function() {
                    if (Ext.getCmp("searchGeneName").getValue() !== "") {
                        addSearchResultsToGrid(Ext.getCmp("searchGeneName").getValue());
                    }
                }
            },{
                text: "Close",
                handler: function() {
                    searchResultStore.removeAll();
                    win.close();
                }
            }],
            items:[{
                xtype:"fieldset",
                title:"Search",
                autoHeight:true,
                items:[{
                    xtype:"textfield",
                    fieldLabel:"Gene Name",
                    name:"searchGeneName",
                    id:"searchGeneName"
                }]
            }]
        });

        // search results list
        var searchResultsGrid = new Ext.grid.GridPanel({
            id: "searchResultsGrid",
            title: "Search Results",
            store: searchResultStore,
            columns: [{
                id: "geneName",
                header: "Gene Name",
                sortable: true,
                dataIndex: "displayName"
            },{
                id: "ensemblGeneId",
                header: "Ensembl Gene Id",
                sortable: true,
                dataIndex: "ensemblGeneId"
            }],
            viewConfig: {
                forceFit: true
            },
            sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
            stripeRows: true,
            autoHeight: true,
            width: 400,
            border: false,
            tbar: [
                new Ext.Button({
                    id: "addSearchResultButton",
                    text: "Add Selected Gene",
                    handler: onAddSearchGene,
                    disabled: true,
                    icon: '../../images/icons/add.png'
                })
            ],
            listeners: {
                rowclick: onSearchResultSelect
            }
        });

        // panel to hold both above components
        var geneSearchPanel = new Ext.Panel({
            autoWidth: true,
            height: 300,
            border: false,
            renderTo: "content",
            layout: "border",
            items: [
                {
                    id: "searchNorth",
                    region: "north",
                    height: 110,
                    split: true,
                    items: [
                        geneSearchForm

                    ]
                },
                {
                    id: "searchCenter",
                    region: "center",
                    split: true,
                    items: [
                        searchResultsGrid
                    ]
                }
            ]
        })

        var win = new Ext.Window({
            id: "searchWindow",
            title: "Add Gene",
            modal: true,
            width: 400,
            autoHeight: true,
            items: [
                geneSearchPanel
            ]
        });
        win.show();
    }

    function onDeleteGene() {
        var record = getSelectedGene();
        if (!record) return;
        geneListStore.remove(record);
        Ext.getCmp("deleteGeneButton").disable();
    }

    function onDeleteAllGenes() {
        geneListStore.removeAll();
    }

    function getSelectedGene() {
        var grid = Ext.getCmp("geneListGrid");
        if (grid.getSelectionModel().getSelected()) {
            return grid.getSelectionModel().getSelected();
        }
        else return undefined;
    }

    function searchForGeneList(textareaValue) {
        if (textareaValue) {
            var terms = textareaValue.split("\n");
            if (terms != null) {
                // show progress bar
                Ext.MessageBox.show({
                    title: 'Please wait',
                    msg: 'Searching...',
                    progressText: '0% completed...',
                    width:300,
                    progress:true,
                    closable:false                    
                });

                var nTotal = 0;
                var nAdded = 0;
                var nNotFound = 0;
                var nSkipped = 0;
                var allDone = false;
                var notFoundList = "";
                var progressCheck = function() {
                    return function() {
                        if (nAdded + nNotFound + nSkipped == nTotal) {
                            Ext.MessageBox.hide();
                            if (nNotFound == 0) {
                                //Ext.MessageBox.alert("Results", "All genes added, " + nAdded + " in total.")
                            } else {
                                Ext.MessageBox.alert("Results", nAdded + " genes added, " + nNotFound + " not found: <br>" + notFoundList);
                            }
                            allDone = true;
                        } else {
                            var pct = (nAdded + nNotFound) / nTotal;
                            Ext.MessageBox.updateProgress(pct, Math.round(100 * pct) + '% completed');
                        }
                    };
                };

              // kick off searches
                nTotal = terms.length;
                for (var i = 0; i < terms.length; i++) {
                    if (terms[i] != null && terms[i] != "") {
                        searchForGene(terms[i], function(entries, searchedTerm) {
                            if (entries != null && entries.length > 0) {
                                // add first entry
                                addSearchRecordToGeneStore(entries[0]);
                                nAdded++;
                            } else {
                                nNotFound++;
                                notFoundList += searchedTerm + "<br>";
                            }
                            setTimeout(progressCheck(), 500);
                        });
                    } else {
                        nSkipped++;
                        setTimeout(progressCheck(), 500);
                    }
                }
                // check status until done
                //                for(1 && (nAdded+nNotFound) < nTotal) {
                //                for(var i=0; i<nTotal && !allDone; i++){
                //                    setTimeout(progressCheck(i), i * 500);
                //                }
            }

        }

    }

    function addSearchResultsToGrid(term) {
        searchResultStore.removeAll();
        searchForGene(term, function(entries, searchedTerm) {
            if (entries != null && entries.length > 0) {
                for (var i = 0; i < entries.length; i++) {
                    searchResultStore.add(entries[i]);
                }
                // select first element
                onSearchResultSelect();
                Ext.getCmp("searchResultsGrid").getSelectionModel().selectFirstRow();
            } else {
                Ext.MessageBox.alert('Search', 'No search results for: ' + searchedTerm);
            }
        });
    }

    function searchForGene(term, callback) {
        var gqlQuery = "select ensembl_gene_id, gene_label, start, end, strand, chromosome_name where gene_label='" + term + "' limit 1000";
        var searchUrl = "/chrom-features-datasource/datasource/genes";
        var query = new google.visualization.Query(searchUrl + "?tq=" + gqlQuery);
        query.send(function(response) {
            var entries = [];
            if (response.isError()) {
                // alert("Error in query: " + response.getMessage() + ":" + response.getDetailedMessage());
            } else {
                var resultTable = response.getDataTable();
                if (resultTable != null && resultTable.getNumberOfRows() > 0) {
                    var idToIndex = getIdToIndex(resultTable);
                    var nRows = resultTable.getNumberOfRows();
                    for (var r = 0; r < nRows; r++) {
                        var entry = new SearchGeneRecord({
                            displayName: resultTable.getValue(r, idToIndex['gene_label']),
                            ensemblGeneId: resultTable.getValue(r, idToIndex['ensembl_gene_id']),
                            start: resultTable.getValue(r, idToIndex['start']),
                            stop: resultTable.getValue(r, idToIndex['end']),
                            strand: resultTable.getValue(r, idToIndex['strand']),
                            chromosomeName: resultTable.getValue(r, idToIndex['chromosome_name'])
                        });
                        entries[r] = entry;
                    }
                }
            }
            callback(entries, term);
        });
    }

    function getIdToIndex(table) {
        var idToIndex = {};
        var ncols = table.getNumberOfColumns();
        for (var i = 0; i < ncols; i++) {
            idToIndex[table.getColumnId(i)] = i;
        }
        return idToIndex;
    }


    function onAddSearchGene() {
        // TODO : get selection from searchResultsGrid and store it in geneListStore
        var grid = Ext.getCmp("searchResultsGrid");
        var records = grid.getSelectionModel().getSelections();
        for (var i = 0; i < records.length; i++) {
            // TODO : check that gene doesn't alraedy exist in list
            addSearchRecordToGeneStore(records[i]);
        }
        searchResultStore.removeAll();
        Ext.getCmp("searchWindow").close();
    }

    function addSearchRecordToGeneStore(record) {
        var gRecord = new GeneListRecord({
            displayName: record.get("displayName"),
            ensemblGeneId: record.get("ensemblGeneId"),
            start: record.get("start"),
            stop: record.get("stop"),
            strand: record.get("strand"),
            chromosomeName: record.get("chromosomeName"),
            exonViewLink: createExonViewLink(record)
        });
        geneListStore.add(gRecord);
    }

    function createExonViewLink(record) {
        if (record) {
            var start = record.get("start");
            var center = start;
            var end = record.get("stop");
            var strand = record.get("strand");
            var chromosomeName = record.get("chromosomeName");
            var expandRegion = 200;

            if (start && end && strand && chromosomeName) {
                var url = "exon_visualization.html";
                var params = "start=" + start + "&end=" + end + "&chr=" + chromosomeName + "&strand=" + strand + "&center=" + center + "&expandBy=" + expandRegion;
                var title = record.get("displayName") + " - Chromosome: " + chromosomeName;
                return "<a href=\"javascript:loadVisContent('" + url + "','" + title + "','" + params + "', true)\"><img src='../../images/icons/application_view_tile.png' style='vertical-align: bottom'> View Exon Expression Data</a>";
            }
        }
        return "View Unavailable";
    }


    function onSearchResultSelect() {
        Ext.getCmp("addSearchResultButton").enable();
    }

    function onGeneSelect() {
        Ext.getCmp("deleteGeneButton").enable();
    }

    function resetPrivateMemberVariables() {
        rootComponent = null;
        sampleSelectInstance = null;
    }

    function returnEmptyComponent() {
        return mainPanel = new Ext.Panel({
            autoWidth: true,
            layout: 'fit',
            border: false
        });
    }

    // public
    return {
        // public properties

        // public methods
        getComponent: function() {
            if (rootComponent) {
                return rootComponent;
            } else {
                return returnEmptyComponent();
            }
        },

        getSampleSelection: function() {
            return sampleSelectInstance.getSelectedSamples();
        },

        init: function(sampleSelectorInstance, callbackFcn) {
            resetPrivateMemberVariables();

            sampleSelectInstance = sampleSelectorInstance;
            var sampleSelectorComponent = sampleSelectorInstance.getComponent();
            if (sampleSelectorComponent == null) Ext.MessageBox.alert("No Sample Selector Component Specified");

            // gene list component
            var geneListComponent = new Ext.grid.GridPanel({
                id: "geneListGrid",
                title: "Step 2. Select Genes",
                store: geneListStore,
                columns: [{
                    id: "geneName",
                    header: "Gene Name",
                    sortable: true,
                    dataIndex: "displayName"
                },{
                    id: "ensemblGeneId",
                    header: "Ensembl Gene Id",
                    sortable: true,
                    dataIndex: "ensemblGeneId"
                },{
                    id: "exonViewLink",
                    header: "Exon View",
                    sortable: false,
                    dataIndex: "exonViewLink"
                }],
                viewConfig: {
                    forceFit: true
                },
                sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
                stripeRows: true,
                height: 200,
                autoWidth: true,
                border: false,
                tbar: [
                    new Ext.Button({
                        id: "addGeneListButton",
                        text: "Add List of Genes",
                        handler: onAddGeneList,
                        icon: '../../images/icons/table_add.png'
                    }),
                    new Ext.Button({
                        id: "addGeneButton",
                        text: "Add Single Gene",
                        handler: onAddGene,
                        icon: '../../images/icons/add.png'
                    }),
                    new Ext.Button({
                        id: "deleteGeneButton",
                        text: "Remove Selected Gene",
                        handler: onDeleteGene,
                        disabled: true,
                        icon: '../../images/icons/delete.png'
                    }),
                    new Ext.Button({
                        id: "deleteAllGenesButton",
                        text: "Remove All",
                        handler: onDeleteAllGenes,
                        icon: '../../images/icons/delete.png'
                    })
                ],
                listeners: {
                    rowclick: onGeneSelect
                }
            });


            // setup root component
            rootComponent = new Ext.Panel({
                border: true,
                autoHeight: true,
                autoWidth: true,
                items: [
                    {
                        id: "mainNorth",
                        region: "north",
                        split: true,
                        items: [
                            sampleSelectorComponent
                        ]
                    },
                    {
                        id: "mainCenter",
                        region: "center",
                        split: true,
                        layout: 'fit',
                        items: [
                            geneListComponent
                        ]
                    }
                ]
            });

            geneListStore.removeAll();
            searchResultStore.removeAll();

            callbackFcn();
        }
    };
}
        ();


//function vchromo_load_data(uri, gqlQuery, callback) {
//    //alert("load_table(" + gqlQuery + ")");
//
//    var query = new google.visualization.Query(uri + "?tq=" + gqlQuery);
//    query.send(function(response) {
//        if (response.isError()) {
//            // alert("Error in query: " + response.getMessage() + ":" + response.getDetailedMessage());
//            callback(null);
//        }
//        callback(response.getDataTable());
//    });
//}






