Ext.namespace( 'Funcassociate.app' );

// the original Ext.QuickTips methods register, unregister, and tips,
// whose definitions are shown below, were buggy since they could be
// called before the local variable tip was defined...

//         register : function(){
//             tip.register.apply(tip, arguments);
//         },

        
//         unregister : function(){
//             tip.unregister.apply(tip, arguments);
//         },

        
//         tips :function(){
//             tip.register.apply(tip, arguments);
//         }

// ...this fixes them:
Funcassociate.VOID = function () {
  var xqt = Ext.QuickTips;
  var sheesh = [ 'register', 'unregister', 'tips' ];
  for ( var i = 0; i < sheesh.length; ++i ) {
    var mn = sheesh[ i ];
    var m = xqt[ mn ];
    xqt[ mn ] = function () {
      if ( xqt.getQuickTip() ) m();
    }
  }
} ();

Funcassociate.EATReader = Ext.extend( Ext.data.DataReader, {
  readRecords: function ( result ) {
    var table = result.table;
    var n_rows = table.length;

    var row_headers = result.row_headers;
    var col_headers = result.column_headers;

    var recordType = this.recordType;
    var row_header_key = recordType.prototype.fields.items[ 0 ].name;

    var records = new Array( n_rows );

    for ( var i = 0; i < n_rows; i++ ){
      var values = {};
      values[ row_header_key ] = row_headers[ i ];
      var row = table[ i ];
      for ( var k = 0, len = row.length; k < len; ++k ) {
        values[ col_headers[ row[ k ] ] ] = true;
      }
      
      var record = new recordType( values, null );
      record.json = row;
      records[ i ] = record;
    }
    return { records: records, totalRecords: records.length };
  }
} );

Funcassociate.ResultStore = Ext.extend( Ext.data.Store, {
  sortData: function ( f, direction ) {
    var g = f == 'adjusted_p_value' ? 'p_value' : f;
    return Funcassociate.ResultStore.superclass.sortData.call( this, g, direction );
  }
} );

Funcassociate.GridSelectionModel = Ext.extend( Ext.grid.AbstractSelectionModel, {
  init: function ( g ) {},
  lock: function () {},
  unlock: function () {},
  isLocked: function () {}
} );

Funcassociate.app.make_result_panels = function () {

  var NULL_SEL_MODEL = new Funcassociate.GridSelectionModel();
  var RENDER_FLOAT = function ( value ) {
    return value.toPrecision( 4 );
  };

  var FIELDS = [
                 { name: 'result-N', type: 'int' },
                 { name: 'result-M', type: 'int' },
                 { name: 'result-X', type: 'int' },
                 { name: 'result-LOD', type: 'float' },
                 { name: 'result-P', type: 'float' },
                 { name: 'result-P-adj', type: 'float' },
                 { name: 'result-Gene-Ontology-ID' },
                 { name: 'result-Gene-Ontology-Attribute' }
               ];

  var READER = new Ext.data.ArrayReader( {}, Ext.data.Record.create( FIELDS ) );

  var COLUMNS = [
                  {
                    tooltip: "Number of entities in query having the row's attribute"
                  },
                  {
                    tooltip: "Size of most surprising subquery for the row's attribute"
                  },
                  {
                    tooltip: "Total number of entities having the row's attribute"
                  },
                  {
                    renderer: RENDER_FLOAT,
                    tooltip: 'Logarithm (base 10) of the odds ratio'
                  },
                  {
                    width: 90,
                    renderer: RENDER_FLOAT,
                    tooltip: 'p-value'
                  },
                  {
                    header: 'P_adj',
                    width: 100,
                    tooltip: 'Resampling-adjusted P-value'
                  },
                  {
                    width: 110
                  },
                  {
                    width: 150
                  }
                ];

  for ( var i = 0; i < COLUMNS.length; ++i ) {
    var c = COLUMNS[ i ];
    var n = FIELDS[ i ].name;
    c.dataIndex = n;
    if ( !c.header )
      c.header = n.replace( /^result-/, '' ).replace( /\s+/g, '-' );
  }

  var _make_result_grid = function ( which, have_both, columns, data ) {

    var col_model = new Ext.grid.ColumnModel( { columns: columns,
    											defaults: {
    												width: 50,
    												sortable: true
    											}
    										  } );

    var store = new Funcassociate.ResultStore( {
      reader: READER,
      proxy: new Ext.data.MemoryProxy( data )
    } );
    var sortDir = 'ASC';
    if(which == 'over') 
    	sortDir = 'DESC';
    store.setDefaultSort('result-LOD', sortDir);

    var tab_title = 'Results';
    if ( have_both ) tab_title += ' (' + which + ')';

    var grid = new Ext.grid.GridPanel( {
      id: 'result-grid-' + which,
      store: store,
      colModel: col_model,
      selModel: NULL_SEL_MODEL,
      cls: 'result-grid',
      stripeRows: true,
      trackMouseOver: false,
      title: tab_title,
      region: 'center',
      autoExpandColumn: columns[ columns.length - 1 ].id
    } );

    store.load( {} );

    return grid;
  };

  return function ( result ) {
    var info = result.request_info;

    var unordered = info.mode == 'unordered';
    var n_fields = FIELDS.length;
    if ( unordered ) n_fields--;

    var min_value = 1/info.reps;
    var render_padj = function ( padj ) {
      return padj ? RENDER_FLOAT( padj ) : '<' + min_value;
    };

    var have_both = result.over && result.under;
    var panels = { over: null, under: null };

    for ( var which in panels ) {
      var data = result[ which ];
      if ( data && data.length > 0 ) {
        var columns = Array( n_fields );
        for ( var i = 0, j = 0; j < n_fields; ++i ) {
          var c = COLUMNS[ i ];
          var h = c.header;
          if ( unordered && h == 'M' ) continue;
          var k = {};
          for ( var f in c ) { k[ f ] = c[ f ] }
          if ( h == 'P_adj' ) k.renderer = render_padj;
          if ( j == n_fields - 1 ) k.id = FIELDS[ i ].name + '-' + which;
          columns[ j ] = k;
          ++j;
        }
        panels[ which ] = _make_result_grid( which, have_both, columns, data );
      }
      else {
        delete panels[ which ];
      }
    }
    
    if(!panels.over && !panels.under) {
    	return null;
    }

    return panels;
  };

}();

Funcassociate.app.make_info_panel = function () {
  var BEGIN =
    "<li style='padding-left: 10px; list-style-position: inside; list-style-type: disc;'>";
  var END = '</li>';

  return function ( result ) {
//	  debugger;
    var info = result.request_info;
    var items = [];
    var qs = info.query_size;
    items.push( "<b>Number of entities in query</b>: " + qs );
    var oqs = info.original_query_size;
    if ( oqs && oqs != qs )
      items.push( "<b>Original number of entities in query</b>: " + oqs );

    var gss = info.genespace_size;
    items.push( "<b>Total number of entities</b>: " + gss );
    var ogss = info.original_genespace_size;
    if ( ogss && ogss != gss )
      items.push( "<b>Original total number of entities</b>: " + ogss );

    var as = info.associations_size;
    items.push( "<b>Total number of attributes</b>: " + as );
    var oas = info.original_associations_size;
    if ( oas && oas != as )
      items.push( "<b>Original total number of attributes</b>: " + ogss );

    var tr = info.translation_required;
    items.push( "<b>Translation required</b>: " + ( tr ? 'yes' : 'no' ) );

    if ( tr ) items.push( "<b>Translation coverage</b>: " + info.coverage );

    items.push( "<b>Mode</b>: " + info.mode );
    items.push( "<b>Number of simulations</b>: " + info.reps );
    items.push( "<b>Adjusted P-value cutoff</b>: " + info.cutoff );
    items.push( "<b>Over/under</b>: " + info.which );
    items.push( "<b>Evidence codes</b>: " + info.support );

    var s = "<h1>Results in the tables below were generated using:</h1><ul>";
    for ( var i = 0; i < items.length; ++i ) {
      s += BEGIN + items[ i ] + END;
    }
    
    return new Ext.Panel( {
      autoScroll: true,
      html: s,
      bodyStyle: 'background-color: #F1F1F1; padding: 5px;',
      title: 'Request info'
    } );
  }
}();

Funcassociate.app.make_warnings_panel = function () {
  var BEGIN =
    "<li style='padding-left: 10px; list-style-position: inside; list-style-type: disc;'>" +
    "<span style='color: green'>";
  var END = "</span></li>";

  return function ( result ) {
    var warnings = result.input_warnings || [];
    var n_warnings = warnings.length;

    if ( ! n_warnings ) return null;

    var s = "<h1>Warnings:</h1><ul>";

    for ( var i = 0; i < n_warnings; i++ ) {
      s += BEGIN + warnings[ i ] + END;
    }

    s += "</ul>";

    return new Ext.Panel( {
      autoScroll: true,
      html: s,
      bodyStyle: 'background-color: #F1F1F1; padding: 5px;',
      title: 'WARNINGS'
    } );
  }
}();

Funcassociate.app.make_eat_panel = function () {
  var NULL_SEL_MODEL = new Funcassociate.GridSelectionModel();
  var DEFAULT_PAGE_SIZE = 25;
  var FIELD_0 = { name: 'entity' };
  var COL_0 = {
                header: "Entity",
                width: 80,
                sortable: false,
                menuDisabled: true,
                dataIndex: FIELD_0.name
              };

  return function ( result, page_size ) {
    page_size = page_size || DEFAULT_PAGE_SIZE;
    var row_headers = result.row_headers;
    var col_headers = result.column_headers;
    var n_cols = col_headers.length;

    var render_eat_cell = function ( value, p, row, row_index, col_index, store ) {
      if ( value ) {
        p.css = 'eat-cell-true';
        var entity = row_headers[ row_index ];
        var attrib = col_headers[ col_index - 1 ];
        p.attr = "title='Entity " + '"' + entity + '"' + ' has attribute "' + attrib + '"' + "'" ;
      }
      return "";
    };
      
    var recordArray = Array( n_cols + 1 );
    var columnArray = Array( n_cols + 1 );

    recordArray[ 0 ] = FIELD_0;
    columnArray[ 0 ] = COL_0;

    var col_dict = result.column_dict;
    for ( var j = 0; j < n_cols; j++ ) {
      var term = col_headers[ j ];
      recordArray[ j + 1 ] = { name: term };
      columnArray[ j + 1 ] = {
                               header: term,
                               width: 80,
                               align: 'center',
                               sortable: false,
                               menuDisabled: true,
                               dataIndex: term,
                               renderer: render_eat_cell,
                               tooltip: col_dict[ term ]
                             };
    }
    
    var record = Ext.data.Record.create( recordArray );
    var reader = new Funcassociate.EATReader( null, record );
    var proxy = new Ext.ux.data.PagingMemoryProxy( result );

    var store = new Ext.data.Store( {
      reader: reader,
      proxy: proxy,
      data: result
    } );

    var toolbar = new Ext.PagingToolbar( {
      pageSize: page_size,
      store: store,
      displayInfo: true,
      displayMsg: 'Displaying results {0} - {1} of {2}',
      emptyMsg: "No results to display"
    } );

    var grid = new Ext.grid.GridPanel( {
      id: 'entity-attribute-grid',
      store: store,
      columns: columnArray,
      selModel: NULL_SEL_MODEL,
      stripeRows: true,
      trackMouseOver: false,
      cls: 'eat-grid',
      title: 'Entity-Attribute Table',
      bbar: toolbar
    } );

    store.load( { params: { start: 0, limit: page_size } } );

    return grid;
  };

}();

Funcassociate.app.make_json_panel = function ( json ) {
  var s = '<pre>' + json + '</pre>';
  return new Ext.Panel( {
    id: 'json-panel',
    html: s,
    layout: 'fit',
    autoScroll: true,
    title: 'JSON'
  } );
};

Funcassociate.app.make_url_panel = function ( url ) {
  var s = '<pre>' + url + '</pre>';
  return new Ext.Panel( {
    id: 'url-panel',
    html: s,
    layout: 'fit',
    autoScroll: true,
    title: 'URL'
  } );
};

