var ePrints = {};

ePrints.dataTable = Class.create({
  
    initialize: function(id, filterEl) {
      this.cellItems = [];
      this.modCells = [];
      this.rows = [];
      this.header = [];
      this.initTable(id);

      this.filter = new ePrints.Filter(this, filterEl);
    },
  
    initTable: function(id){
      var _rowNum = 0;
      var _colNum = 0;
      var _items = this.cellItems; 
      var _rows = this.rows;
      var _cells = this.modCells
      $$('#'+id+' tr').each(function(_tr){
          _cells[_rowNum] = [];
          _tr.childElements().grep(new Selector("td")).each(function(_td){
              var _cell = {
                itemNum: _items.length, 
                rowNum: _rowNum,
                colNum: _colNum,
                el: _td,
                cls: "",
                updated: false
              }
        
                _items.push(_td.cloneNode(true));
              _cells[_rowNum][_colNum] = _cell;
              _colNum++;
            })
      
          if (_colNum != 0) {
            _rows.push({
                el: _tr,
                  rowNum: _rowNum
                  });
            _rowNum++;
          }
          _colNum = 0;
        })

      this.header = $$("#"+id+" th");
    },
  
    getLine: function(_lineType, _lineNum){
      var _line = [];
      var _cells = this.modCells;
      var r=0;
      var c=0;
      if(_lineType == "col"){
        while(_cells[r]!=undefined && _cells[r][_lineNum]!=undefined){
          _line.push(_cells[r][_lineNum]);
          r++;
        }
      }else{
        while(_cells[_lineNum][c]){ 
          _line.push(_cells[_lineNum][c]);
          c++;
        }
      }
      return _line; 
    },
  
    swapLine: function(_lineType, _line1, _line2){
      var _l1 = this.getLine(_lineType, _line1);
      var _l2 = this.getLine(_lineType, _line2);
      for (var i = 0; i < _l1.length; i++) {
        this.swapCell(_l1[i],_l2[i]);
      }
    },
  
    swapCell: function(_c1, _c2){
      this.replaceCell(_c2, this.replaceCell(_c1, _c2));
    },
  
    replaceCell: function(_cFrom, _cTo){ 
      var _replacedCell = Object.clone(_cFrom);
      _cFrom.itemNum = _cTo.itemNum;
      _cFrom.updated = true;
      _cFrom.rowNum = _cTo.rowNum;
      _cFrom.colNum = _cTo.colNum;
      return _replacedCell; 
    },

    sort: function(_colNum,_type, _reverse){ 
      var _cells = this.modCells;
      var _this = this;
      var _sortingCells = [];
 
      for (var r = 0; r < _cells.length; r++) {
        _sortingCells.push(_cells[r][_colNum]);
      }
    
   
      function _sort(){ 
        switch(_type){
        case "string": 
        for (var k = 0; k < _sortingCells.length; k++) {
          for (var i = 0; i < _sortingCells.length-1; i++) { 
            var _cur = getJustText(_sortingCells[i].el.innerHTML, true);
            var _next = getJustText(_sortingCells[i+1].el.innerHTML, true);
            for(var j=0;j<=_cur.length && j<=_next.length;j++){
              var _curValue = ascii_value(_cur.charAt(j).toUpperCase());
              var _nextValue = ascii_value(_next.charAt(j).toUpperCase());
              swap(_curValue,_nextValue, i);
              break;
            }
          }
        }
        break;
        
        case "number":
        for (var k = 0; k < _sortingCells.length; k++) {
          for (var i = 0; i < _sortingCells.length - 1; i++) {
            var _curValue = (!isNaN(parseFloat(getJustText(_sortingCells[i].el.innerHTML, true))))?parseFloat(getJustText(_sortingCells[i].el.innerHTML, true)) : 0;
            var _nextValue = (!isNaN(parseFloat(getJustText(_sortingCells[i+1].el.innerHTML, true))))?parseFloat(getJustText(_sortingCells[i+1].el.innerHTML, true)) : 0;
            swap(_curValue,_nextValue, i);
          }
        }
        break; 
        
        case "date": 
        for (var k = 0; k < _sortingCells.length; k++) {
          for (var i = 0; i < _sortingCells.length - 1; i++) {
            var _cur = parseInt(getDate(getJustText(_sortingCells[i].el.innerHTML, false)));
            var _next = parseInt(getDate(getJustText(_sortingCells[i+1].el.innerHTML, false)));
            
            swap(_cur,_next, i);
          }
        }
        break;
          
        }
      }
    
      function getDate(_str){
        var date = _str.replace(/^\s+/,'').replace(/,/,'').split(' '); 
        var d = "00";
        var y = "9999";
        var m = "00";
        for(var i=0;i<date.length;i++){
          if(isNaN(parseInt(date[i])) && getMonthInNum(date[i]) != undefined){
            m = getMonthInNum(date[i]);
          }else{ 
            if(date[i].length>3){
              y = date[i];
            }else{
              if(!isNaN(parseInt(date[i])))
                d = (date[i].length<2)?"0"+date[i]:date[i];
            }
          }
        }
      
        return String(y+m+d);
      }
    
      function getMonthInNum(_month){
      
        var month = {
          january: "01",
          february: "02",
          march: "03",
          april: "04",
          may: "05",
          june: "06",
          july: "07",
          august: "08",
          september: "09",
          october: "10",
          november: "11",
          december: "12"
        };
        return month[_month.toLowerCase()];
      }
    
      function swap(_curValue, _nextValue, i){
        if (_curValue != _nextValue) {
          if (_curValue > _nextValue) {
            var tmp = _sortingCells[i];
            _sortingCells[i] = _sortingCells[i + 1];
            _sortingCells[i + 1] = tmp;
            _this.swapLine('row', i, i + 1);
          }
        }
      }
    
      function ascii_value(c){
        c = c.charAt(0);
        var i;
        for (i = 0; i < 256; ++i) {
          var h = i.toString(16);
          if (h.length == 1) 
            h = "0" + h;
          h = "%" + h;
          h = unescape(h);
          if (h == c) break;
        }
        return i;
      }
 
      function getJustText(_str,_withSpace){
        _str = _str.stripTags();
        _str = _str.replace(/[\n\r]/g,"").replace(/\"/,'');
        if(_withSpace) _str = _str.replace(/\s+/g,'');
        return _str;
      }
 
      //console.info(_sortingCells);
      _sort();
      if(_reverse) this.reverseSort();
    },
  
    reverseSort: function(){
    
      for(var i=0;i<this.modCells.length/2;i++){
        this.swapLine("row", i, this.modCells.length - i - 1);
      }
    },
  
    addClassName: function(_lineType,_line,_className){
      this.getLine(_lineType, _line).each(function(l){
          l.cls = _className;
          l.updated = true;
        })
    },
    
    render: function(){
      var cells = this.modCells;
      for(var r=0;r<cells.length;r++){
        for(var c=0;c<cells[r].length;c++){
          var _cell = cells[r][c];
          if(_cell.updated){ 
            //_cell.el.replace(this.cellItems[_cell.itemNum]);
            var cnt = ""+ this.cellItems[_cell.itemNum].innerHTML;
            _cell.el.innerHTML = cnt;
            if (_cell.cls != "") { 
              _cell.el.addClassName(_cell.cls);
            }
            _cell.updated = false;
          }
        
          _cell.rowNum = r;
          _cell.colNum = c;
        }
      } 
      // console.info(this.modCells);
      document.fire('table:rendered');
    },
    
    getUniqueItems: function(colNum){
      var uniqueItems = [];
      this.rows.each(function(row){
        if(!row.el.hasClassName("disabled")){
          var td = row.el.select('td')[colNum].innerHTML.strip().stripTags();
          var isUnique = true;
          uniqueItems.each(function(item){
            if (item == td) {
              isUnique = false;
              throw $break;
            }
          });
          if(isUnique) uniqueItems.push(td);
        }
      })
      return uniqueItems;
    }
  });

ePrints.Filter = Class.create({
    table: null,

    filters: {},

    activeFilter: 'none',
    
    _store: [],

    initialize: function(table, filterEl) {
      this.table = table;
      this.initFilters();
      this.render(filterEl);
      this.setupObservers(filterEl);
    },

    initFilters: function() {
      var headers = this.table.header;
      var idx = headers.length;
      while(--idx>=0) {
        if(headers[idx].className.match(/filter/)) {
          this.filters[idx] = {
            name: headers[idx].innerHTML.match(/>([^<]+)</)[1],
            options: []
          };
        }
      }

      var rows = this.table.rows;
      idx = rows.length;
      while(--idx>=0) {
        var cells = rows[idx].el.cells;
        var cidx = cells.length;

        while(--cidx>=0) {
          if(this.filters[cidx]) {
            var option = cells[cidx].innerHTML.match(/>(.+)</)[1];
            var opts = this.filters[cidx].options;
            var oidx = opts.length;
            var addOption = true;
            while (--oidx>=0) {
              if(opts[oidx] == option) addOption = false;
            }

            if(addOption) this.filters[cidx].options.push(option);
          }
        }
      }
      
    },

    render: function(id) {
      var el = $(id);

      var select = '<div class="filter"><select><option value="all">Show All</option>';

      for (var idx in this.filters) {
        var filter = this.filters[idx];
        var optgroup = '<optgroup label="'+filter.name+'">';

        // Setup Options
        var opts = "";
        var oidx = filter.options.length;
        while(--oidx>=0) {
          var opt = filter.options[oidx];
          var option = '<option value="'+opt+'">'+opt+'</option>';
          opts += option;
        }

        optgroup += opts+'</optgroup>';
        select += optgroup;
      }

      select += '</select></div>';
      el.innerHTML += select;
    },

    setupObservers: function(id) {
      var el = $(id);
      var selects = el.getElementsByTagName("select");
      var idx = selects.length;
      while(--idx>=0) {
        $(selects[idx]).observe("change", this.filterChanged.bind(this));
      }
    },

    filterChanged: function(evt) {
      var el = evt.element();

      var selectedFilter = '';
      var options = el.getElementsByTagName("option");
      var idx = options.length;
      while(--idx>=0) {
        var opt = options[idx];
        if(opt.selected) {
          selectedFilter = opt.value;
        }
      }

      if(this.activeFilter != selectedFilter) {
        this.activeFilter = selectedFilter;
        document.fire("filter:changed");
      }

    },

    go: function() {
      var f = this.filters;
      var af = this.activeFilter;
      var rows = this.table.rows;
      var idx = rows.length;

      while(--idx>=0) {
        var storeRow = true;

        for (var k in f) {
          if (af == rows[idx].el.cells[k].innerHTML.match(/>(.+)</)[1] ||
              af == "all") storeRow = false;
        }

        if(storeRow) {
          rows[idx].el.addClassName("disabled");
        } else {
          rows[idx].el.removeClassName("disabled");
        }
      }
    },

    reset: function(id) {
      var el = $(id);
      var selects = el.getElementsByTagName("select");
      var idx = selects.length;
      while(--idx>=0) {
        var oidx = selects[idx].childNodes.length;
        while (--oidx>=0) {
          selects[idx].childNodes[oidx].selected = false;
        }
      }

      this.activeFilters = {};
    }

  });
  
  