/*****************************************************************************
  Usage:
  
  NOTES:
     
  Author: Steven Lee
*****************************************************************************/

Voy.DataGrid = Class.create();
Voy.DataGrid.prototype = {
  initialize: function(cols,options) {
    this.cols = $A();
    this.rows = $A();
    
    this.options = {
      createCell: this._createCell.bind(this),
      createCellName: this._createCellName.bind(this),
      cellNamePrefix: "rows",
      cssPrefix: "dg",
      rowCount: 1,
      autoAddRows: false
    }
    
    this.options = Object.extend( this.options, options );
    
    this.divs = {};
    
    var cells = $A();
    var th = this.node( "th", [ "first" ], "&nbsp;" );
    var tr = this.node( "tr", [ "header" ], [th] );

    // cols { name:, id:, html: }
    for( var i = 0; i < cols.length; i++ ) {
      this.cols[i] = Object.extend( { html: cols[i].name }, cols[i] );
      var th = this.node( "th", ( i == cols.length - 1 ? [ "last", this.cols[i].name ] : [this.cols[i].name] ), this.cols[i].html ) ;
      tr.appendChild( th );
    }
    
    this.divs.thead = this.node( "thead", null, [tr] );
    this.divs.grid = this.node( "tbody", null, null );
    this.divs.table = this.node( "table", null, [ this.divs.thead, this.divs.grid ] );
    this.divs.table.cellSpacing = 0;
    this.divs.container = this.node( "container", null, [ this.divs.table ] );
    this.reset();
  },
  getColumnCount: function() {
    return this.cols.length;
  },
  getRowCount: function() {
    return this.rows.length;
  },
  getCell: function( iRow, iCol ) {
    var rows = this.getRows(iRow);
    return rows[ Voy.ifBlank( iCol, this.iCol ) ];
  },
  getRows: function(iRow) {
    return this.rows[ Voy.ifBlank( iRow, this.iRow ) ];
  },
  getValue: function(iRow,iCol) {
    return $F( this.getCell( iRow, iCol ) );
  },
  setValue: function( iRow, iCol, value ) {
    var cell = this.getCell( iRow, iCol );
    Form.Element.setValue( cell, value );
  },
  getValues: function() {
    var rows = $A();
    
    for( var i = 0; i < this.rows.length; i++ ) {
      var row = $A();
      for( var j = 0; j < this.cols.length; j++ ) {
        row[j] = $F( this.getCell(i,j) );
      }
      rows[i] = row;
    }
    
    return rows;
  },
  populate: function(array) {
    for( var i = 0; i < array.length; i++ ) {
	    var iRow = this.createRow( false );
	    for( var iCol = 0; iCol < this.cols.length; iCol++ ) {
	      this.setValue( iRow, iCol, array[i][iCol] );
	    }
    }
  },
  reset: function() {
    var dg = this;
    this.rows.each( function( row ) {
	    for( var i = 0; i < dg.cols.length; i++ ) {
	      var cell = row[i];
	      Event.stopObserving( cell, "focus", cell.dgdata.onfocus );
	      Event.stopObserving( cell, "kepress", cell.dgdata.onkeypress );
	    };
      
      Element.remove( row.dgdata.tr );
    } );
    
    this.rows = $A();
    (this.options.rowCount).times( function(dg) { dg.createRow(false) }.bind(this,this) );
  },
  deleteRow: function(iRow) {
    iRow = iRow || this.iRow;
    
    if( iRow < 0 || iRow >= this.rows.length ) {
      alert( "Cannot Delete Row #" + ( iRow + 1 ) );
      return -1;
    }
    
    var row = this.rows[iRow];
    
    for( var i = 0; i < this.cols.length; i++ ) {
      var cell = row[i];
      Event.stopObserving( cell, "focus", cell.dgdata.onfocus );
      Event.stopObserving( cell, "kepress", cell.dgdata.onkeypress );
    };
    
    this.rows[iRow] = null;
    this.rows = this.rows.compact();
    Element.remove( row.dgdata.tr );
    
    for( var i = iRow; i < this.rows.length; i++ ) {
      var cell = this.rows[i].dgdata.cells[0];
      cell.innerHTML = i + 1;
    }
    
    if( this.iRow <= 0 ) {
      this.iRow == 0;
    } else if( this.iRow >= this.rows.length ) {
      this.iRow = (this.rows.length - 1);
    }

	  this.activate( this.iRow, this.iCol );
	  return this.iRow;
  },
  createRow: function(activate, dateColumns) {
    activate = ( Voy.isUndefined( activate ) ? true : activate );
    
    var cells = $A();
    var row = $A();
    var nRow = this.rows.length;
    cells[0] = this.node( "td", [ "first" ], nRow + 1 );
    
    for( var i = 0; i < this.cols.length; i++ ) {
    	var isDateColumn = false;
        if (null != dateColumns) {
        	for (col=0; col<dateColumns.length; col++) {
        		if (dateColumns[col] == i) {
        			isDateColumn = true;
        		}
        	}
        }
      var cell = this.options.createCell( nRow, i, this.options.createCellName(nRow, i) );
      this.setClassNames( cell, "cell", [ this.cols[i].name ] );  
      row[i] = cell;
      cell.dgdata = {
        onfocus: this.onfocus.bind( this, cell),
        onkeypress: this.onkeypress.bindAsEventListener(this)
      };
      
      Event.observe( cell, "focus", cell.dgdata.onfocus );
      Event.observe( cell, "keypress", cell.dgdata.onkeypress );
      
      if( isDateColumn ) {
    	  $(cell).setStyle({ width: '75px' });
    	  $(cell).setAttribute("id", "birthdate-" + nRow);
    	  $(cell).setAttribute("value", "");
    	  var imgCell = Voy.img( {src: "/vip/assets/images/icons/calendar.gif", height: "14px", onclick: "popUpCalendar(this, document.getElementById('birthdate-" + nRow + "'),'mm/dd/yyyy', -1, -1)" } );
    	  var spanCell = Voy.span( {style: "white-space:nowrap;" }, [cell, imgCell] );
    	  cells[i+1] = this.node( "td", ( i == this.cols.length - 1 ) ? [ "last", this.cols[i].name ] : [this.cols[i].name], [spanCell] );
      } else {
    	  cells[i+1] = this.node( "td", ( i == this.cols.length - 1 ) ? [ "last", this.cols[i].name ] : [this.cols[i].name], [cell] );
      }
    }
    
    row.dgdata = { tr: this.node( "tr", null, cells ), cells: cells };
    
    if( window.location.href.indexOf('mathmania') < 0 )
      this.divs.grid.appendChild( row.dgdata.tr );
    else {
      if( this.rows.length < 35)
        this.divs.grid.appendChild( row.dgdata.tr );
    }    
      
    this.rows[this.rows.length] = row;
    
    if( activate )
      this.activate( nRow, 0 );
    return nRow;
  },
  setClassNames: function( elem, tagName, subNames ) {
    Element.classNames( elem ).set("");
    Element.addClassName( elem, this.getClassName( tagName ) );
    
    if( subNames != null ) {
      var dg = this;
	    subNames = $A(subNames);
	    subNames.each( function( subName ) {
		    if( Voy.isNotBlank( subName ) ) {
		      Element.addClassName( elem, dg.getClassName(tagName + "-" + subName) );
	      }
	    } );
    }
  },
  node: function( tagName, subNames, html ) {
    var rVal = Builder.node( tagName );
    this.setClassNames(rVal, tagName, subNames );
    
	  if( Voy.isNotBlank( html ) ) {
	    if( Voy.isArray( html ) ) {
	      $A(html).each( function(iHtml) { rVal.appendChild( iHtml ); } );
	    } else {
	      rVal.innerHTML = html;
	    }
	  }
    
    return rVal;
  },
  findRowCol: function(cell) {
    var iRow = 0, iCol = -1;
    for( ;iRow < this.rows.length; iRow++ ) {
      iCol = this.rows[iRow].indexOf( cell );
      if( iCol >= 0 )
        break;
    }
    
    return [iRow, iCol ];
  },
  onkeypress: function(evt) {
    var iCol = 0, iRow = 0;
    var cell = this.getCell();
    var isInputTag = ( this.getCell().tagName.toLowerCase() == 'input' );
    
    switch( evt.keyCode ) {
      case Event.KEY_LEFT:
        var cell = this.getCell();
        if( isInputTag ) {
	        var range = Field.getSelectionRange( this.getCell() );
	        if( $F(cell).length == ( range[1] - range[0] )  || 0 == range[0]  ) {
	          iCol = -1;
	        }
        }
        break;
      case Event.KEY_RIGHT:
        if( isInputTag ) {
	        var range = Field.getSelectionRange( this.getCell() );
	        if( $F(cell).length == ( range[1] - range[0] )  || $F(cell).length == range[1]  ) {
		        iCol = 1;
	        }
        }
        break;
      case Event.KEY_UP:
        if( isInputTag ) {
	        if( cell.tagName.toLowerCase() != 'select' ) {
	          iRow = -1;
	        }
        }
        break;
      case Event.KEY_DOWN:
        if( isInputTag ) {
	        if( cell.tagName.toLowerCase() != 'select' ) {
	          iRow = 1;
	        }
        }
        break;
      default:
		    if( this.options.autoAddRows && this.iRow == this.rows.length - 1 ) {	
		      this.createRow(false);
		    }
        break;
    }
    
    if( iCol != 0 || iRow != 0 )
    {
        this.move( iRow, iCol );
        Event.stop(evt);
    }
  },
  onfocus: function(cell) {
    var rc = this.findRowCol(cell);
    this.iRow = rc[0];
    this.iCol = rc[1];
  },
  move: function( iRows, iCols ) {
    this.activate( this.iRow + iRows, this.iCol + iCols );
  },
  activate: function( iRow, iCol ) {
    if( iRow >= 0 && iRow < this.rows.length && iCol >= 0 && iCol < this.cols.length ) {
	    this.iRow = iRow;
	    this.iCol = iCol;
      setTimeout( function(dg,iRow,iCol) { 
        Field.activate(dg.getCell(iRow,iCol)); 
      }.bind(this, this, iRow, iCol ), 300 );
    }
  },
  isRowEmpty: function(iRow) {
    var row = this.rows[iRow];
    var dg = this;
    
    var rVal = this.cols.any( function(col,index ) {
      return Voy.isNotBlank( dg.getValue(iRow,index) );
    } );
    
    return ! rVal;
  },
  getClassName: function( name ) {
    return this.options.cssPrefix + ( Voy.isBlank( name ) ? "" : ( "-" + name ) );
  },
  getDiv: function(removeParent) {
    if(removeParent && this.divs.container.parentNode)
      Element.remove( this.divs.container );
      
    return this.divs.container;
  },
  _createCell: function(iRow, iCol, name) {
    var input = Voy.input( { type: "text", name: name, autocomplete:"off", value: "" } );
    return input;
  },
  _createCellName: function(iRow,iCol) {
    return this.options.cellNamePrefix + "[" + iRow + "]." + this.cols[ iCol ].name;
  },
  destroy: function() {
  }
}


