/**
 * TGrid class manages a set internal of properties and use
 * a container element in document to retrieve a list of rows
 * from server and display it to the user.
 *
 * Setup an URL and fire different TGrid events from document
 * elements to make a request into a server script and return
 * a list of sorted, paged and filtered records.
 *
 * Handle TGrid events like "rowchange" or "afterrequest" to
 * update row status texts in document or check server response
 * cosistency after a request has been made.
 *
 * @param {String | Element} data: data container element
 */
var TGrid = function(data, info) {
  this.url = '';
  this.data = TDOM.getElement(data);
  this.modal = null;
  this.rowstart = 0;
  this.rowcount = 0;
  this.rowtotal = 0;
  this.sortcol  = 0;
  this.sortmode = 0;
  this.searchcol = 0;
  this.searchmode = 0;
  this.searchstring = '';
  this.changed = false;
  this.params = {};

  this.updating = false;
  this.http = new THttp();
  this.modalWin = null;
  this.modalColor = '#f5f5f5';
  this.modalOpacity = 0.75;
  this.modalMessage = "Requesting data, please wait...";
  this.http.addEventListener("complete", this.handleHttp, this);
}
TGrid.inherits(TEventDispatcher);

/**
 * Jump to the next page
 */
TGrid.prototype.nextPage = function() {
  if (this.rowstart + this.rowcount < this.rowtotal ) {
    this.rowstart = this.rowstart + this.rowcount;
    this.send();
  }
}

/**
 * Go back one page
 */
TGrid.prototype.prevPage = function() {
  if (this.rowstart > 0) {
    this.rowstart = this.rowstart - this.rowcount;
    if (this.rowstart < 0) {
      this.rowstart = 0;
    }
    this.send();
  }
}

/**
 * Set row start
 */
TGrid.prototype.setRowStart = function(value) {
  value = parseInt(value);
  if (!isNaN(value) && value >= 0) {
    if (this.rowstart != value && value < this.rowtotal) {
      this.rowstart = value;
      this.changed = true;
    }
  }
}

/**
 * Set row count
 */
TGrid.prototype.setRowCount = function(value) {
  value = parseInt(value);
  if (!isNaN(value) && value >= 5) {
    if (this.rowcount != value) {
      this.rowcount = value;
      this.changed = true;
    }
  }
}

/**
 * Set search column
 */
TGrid.prototype.setSearchCol = function(value) {
  value = parseInt(value);
  if (!isNaN(value) && value >= 0) {
    if (this.searchcol != value) {
      this.searchcol = value;
      this.changed = true;
    }
  }
}

/**
 * Set search mode
 */
TGrid.prototype.setSearchMode = function(value) {
  value = parseInt(value);
  if (!isNaN(value) && value >= 0) {
    if (this.searchmode != value) {
      this.searchmode = value;
      this.changed = true;
    }
  }
}

/**
 * Set search mode
 */
TGrid.prototype.setSearchString = function(value) {
  if (this.searchstring != value) {
    this.searchstring = value;
    this.changed = true;
  }
}

/**
 * Sort columns
 */
TGrid.prototype.sort = function(col) {
  col = parseInt(col);
  if (!isNaN(col) && col >= 0) {
    if (col == this.sortcol) {
      this.sortmode = this.sortmode == 1 ? 0 : 1;
    } else {
      this.sortcol = col;
      this.sortmode = 0;
    }
    this.send();
  }
}

/**
 * Delete record
 */
this.deleteRow = function(id) {
  var del = false;
  var result = this.msgdlg.show(null,'mtDelete',['mbYes','mbNo'],this.deleteRow,this,arguments);
  if (result == 'mrYes') {
    this.data.Params['del'] = id;
    this.getTableContent();
  }
}

/**
 * Handle RETURN key pressed on input elements
 * and submit grid if data has been changed
 * In some cases, like in search string RETURN hit, set
 * reset parameter to true to put back rowstart to 1
 * as filtered resulset count can vary from current
 * rowtotal
 */
TGrid.prototype.handleSubmit = function(e, reset) {
  e = e || window.event;
  if (e && e.keyCode == 13) {
    if (this.changed) {
      if (reset) {
        this.rowstart = 0;
      }
      this.changed = false;
      this.send();
    }
  }
}

/**
 * Handle HTTP request response and update Grid data and
 * row valies.
 * Server response must be:
 *
 * <grid:rows>rowtotal</grid:rows>
 * <grid:data>html grid data</grid:data>
 */
TGrid.prototype.handleHttp = function(e) {
  this.modalWin.close();
  if (this.http.error) {
    this.dispatch("error", this.http.lastError);
  } else {
    var html = this.http.toString();
    var regex = new RegExp(/<grid:data>([\s\S]*)<\/grid:data>/);
    if (regex.test(html)) {
      this.data.innerHTML = RegExp.$1;
    } else {
      this.dispatch("error", "Unknown server response", html);
    }
    regex = new RegExp(/<grid:rows>([\s\S]*)<\/grid:rows>/);
    if (regex.test(html)) {
      var rowtotal = parseInt(RegExp.$1);
      if (!isNaN(rowtotal) && rowtotal >= 0) {
        this.rowtotal = rowtotal;
      }
    }
  }
  this.dispatch("rowchange", this.rowstart, this.rowcount, this.rowtotal);
}

/**
 * Submit TGrid values to a server script
 * to retrieve table rows
 */
TGrid.prototype.send = function() {
  this.dispatch("beforesend");
  if (!this.modalWin) {
    this.modalWin = new TModalWin();
    this.modalWin.modal = TDOM.getElement(this.modal);
    this.modalWin.color = this.modalColor;
    this.modalWin.opacity = this.modalOpacity;
    this.modalWin.show(this.modalMessage);
  } else {
    this.modalWin.open();
  }
  this.http.clear();
  this.http.addParam('rowstart', this.rowstart);
  this.http.addParam('rowcount', this.rowcount);
  this.http.addParam('sortcol', this.sortcol);
  this.http.addParam('sortmode', this.sortmode);
  this.http.addParam('searchcol', this.searchcol);
  this.http.addParam('searchmode', this.searchmode);
  this.http.addParam('searchstring', this.searchstring);
  for (var i in this.params) {
    this.http.addParam(i, this.params[i]);
  }
  this.http.post(this.url);
}
