// ----------------------------------------------------------------------------
// Grid-Control
// ----------------------------------------------------------------------------

function GridCtrl(gridID) {
  var self = this;

  // Public Properties und Variablen
  this.gridID = gridID;         // div-Tag fuer das Grid

  this.rows = 0;                // Anzahl der Zeilen
  this.row = new Array();       // Content der Zeile

  this.selcol = 0;              // Index in Row[]
  this.selcolhidden = true;     // True: Indexzelle wird nicht angezeigt
  this.selID = 0;               // Selected RowID
  this.autoselect = true;       // Falls nichts ausgewaehlt dann 1. Zeile
  this.sorted=false;            // Grid ist Sortiert

  this.iconview = false;        // Kachelmodus
  this.cols = 0;                // Anzahl der Spalten
  this.col = new Array();       // Content der Spalte
  this.colwidth = new Array();  // Breite der Spalte
  this.colalign = new Array();  // Ausrichtung der Spalte  0=links 1=center 2=rechts 3=img
  this.colstyle = new Array();  // Spalte hat eigene Class-Definition

  this.colenum = new Array();   // Spalte hat Wertetabelle
  this.colform = new Array();   // Spaltenformat 0=Normal, 1=Datum, 2=Enum

  this.imgpath = '../img/';     // Verzeichnis fuer Bilder

  // private Variablen
  var rowwidth = 0;             // Breite des inneren Grids
  var sortcol = 0;              // Sortierspalte
  var oldsortcol = null;        // Alte sortierte Spalte
  var splitx = 0;               // Splitting x
  var splitsz = 0;              // Splitting Size

  // ---------------------------------------------
  // priv. Methoden
  // ---------------------------------------------

  // Wrapper
  function getTagVal(obj,tag) {
    return obj.getElementsByTagName(tag)[0].firstChild.nodeValue;
  }

  // Div Tag erzeugen
  var createDiv = function(r, c, content ) {

    // Neue Zelle erstellen
    var cell = document.createElement('div');

    cell.id = "r"+r+"c"+c;
    if (content === null || content == '') {
      cell.innerHTML = ' &nbsp;';
    } else {
      cell.innerHTML = content;
    }

    if (r < 0) {
      // Kopfzeile
      cell.sortDir = 0;
      cell.colnr = c;

      // Events
      cell['onmouseover'] = self.headHighlight;
      cell['onmouseout'] = self.headNormal;
      cell['onclick'] = self.columnSort;

      if (!self.iconview) {
        cell['onmousedown'] = self.startResize;
      }

      // Style
      cell.style.width = self.colwidth[c];
      setClass(cell, 'header');

    } else {
      // Normale Zelle
      cell.rownr = r;

      // Events
      cell['onclick'] = self.selevent;
      cell['ondblclick'] = self.dblclick;

      // Autoselect
      if (self.autoselect && self.selID == 0 ) {
        self.selID = self.row[r][self.selcol];
      }

      // Style
      if (self.colstyle[c]!= '') {
        setClass(cell, self.colstyle[c]);
      } else {

        cell.style.width = self.colwidth[c];
        if (self.colalign[c] == 1) {
          cell.style.textAlign = 'center';
        } else if (self.colalign[c] == 2) {
          cell.style.textAlign = 'right';
        }

        if (self.row[r][self.selcol] == self.selID) {
          setClass(cell, 'cellsel');
        } else {
          setClass(cell, (r%2==0)?'cell2':'cell' );
        }
      }

    }
    return cell;
  };

  // Vergleichsfunktionen fuer Sortierung
  var compAsc = function(r1, r2) {
    return r1[sortcol] < r2[sortcol] ? -1 :
           r1[sortcol] > r2[sortcol] ? 1 : 0;
  };
  var compDesc = function(r1, r2) {
    return r1[sortcol] > r2[sortcol] ? -1 :
           r1[sortcol] < r2[sortcol] ? 1 : 0;
  };

  // ---------------------------------------------
  // Grid aufbauen
  // ---------------------------------------------

  // Spalte hinzufuegen
  this.addCol = function(ctitel, cwidth, calign, cstyle, cform, cenum ) {
    if (ctitel === null) {
      return 0;
    }
    this.col[this.cols]      = ctitel;
    this.colwidth[this.cols] = (cwidth === null ) ? 0 : cwidth;
    this.colalign[this.cols] = (calign === null) ? 0 : calign;
    if (cform === null || cstyle === undefined) {
      this.colstyle[this.cols] = '';
    } else {
      this.colstyle[this.cols] = cstyle;
    }
    this.colform[this.cols]  = (cform === null) ? 0 : cform;
    this.colenum[this.cols]  = (cenum === null) ? 0 : cenum;

    this.cols++;
    return this.cols;
  };

  // Zeile hinzufuegen
  this.addItem = function(rowdat) {
    this.row[this.rows] = rowdat;
    this.rows++;
    return this.rows;
  };

  // Icon hinzufuegen
  this.addIcon = function(id, icon, titel, subtitel) {
    var rowdat = new Array();
    rowdat[0] = id;
    rowdat[1] = '<img src="'+self.imgpath+icon+'">';
    rowdat[2] = titel;
    rowdat[3] = subtitel;
    this.row[this.rows] = rowdat;
    this.rows++;
    return this.rows;
  };

  // XML Datensatz einfuegen
  this.setXML = function(xmlobj) {

    // Loesche alte Zeilen
    self.rows = 0;
    delete self.row;
    self.row = new Array();

    var wert = '';

    // neuen Datensaetze einlesen
    var rows = xmlobj.getElementsByTagName("row");
    if (rows !== undefined) {
      // alle Zeilen
      for (var i=0;i<rows.length;i++) {
        var feld = rows[i].getElementsByTagName("entry");
        // alle Felder
        var rowdat = new Array();
        for (var f=0;f<feld.length;f++) {
          if (feld[f].firstChild !== null) {
             wert = feld[f].firstChild.nodeValue;
             if (self.colform[f] == 1) {
               // Datum im Format tt.mm.jjjj
               wert = wert.substr(8, 2)+'.'+wert.substr(5, 2)+'.'+wert.substr(0, 4);
             }
             if (self.colform[f] == 2) {
               // Enum
               wert = self.colenum[f][wert];
             }
            if (self.iconview == true && f == 1) {
              // bei iconview ist der 2.Wert ein icon
              rowdat[f]='<img src="'+self.imgpath+wert+'">';
            } else {
              rowdat[f]=wert;
            }
          } else {
            rowdat[f]='';
          }
        }
        self.row[self.rows] = rowdat;
        self.rows++;
      }
    } else {
      self.selID = 0;
    }
    // Anzahl der Zeilen zurueck
    return self.rows;
  };


  // ---------------------------------------------
  // Anzeige
  // ---------------------------------------------

  // Grid anzeigen
  this.draw = function(gridID) {

    if (gridID !== null && gridID !== undefined) { self.gridID = gridID; }
    if (self.gridID === null || self.gridID === undefined) { self.gridID = 'grid1'; }

    var gr = document.getElementById((self.gridID));
    if (!gr) { alert(" Kein Grid mit ID: "+self.gridID); }

    // Alte Struktur loeschen
    var og = document.getElementById((self.gridID)+'innergrid');
    if (og) { og.parentNode.removeChild(og); }
    delete og;

    // Neue Struktur aufbauen
    var ig = document.createElement('div');
    ig.id = (self.gridID)+'innergrid';
    setClass(ig,'innergrid');
    gr.appendChild(ig);

    // Kopfzeile immer, wg sortieren
    var rw = document.createElement('div');
    rw.id = 'row-1';
    rw.style.clear = 'both';
    for (var c=0;c<this.cols;c++) {
      if (!(c == self.selcol && self.selcolhidden)) {
        rw.appendChild(createDiv(-1, c, this.col[c]));
      }
    }
    ig.appendChild(rw);

    // Spaltenbreite setzten
    rw.style.width = '100%';
    rowwidth = rw.offsetWidth;;

    // Grid
    for (var r=0;r<this.rows;r++) {

      // Neue Zeile
      var rw2 = document.createElement('div');
      rw2['onclick'] = self.selevent;
      rw2.id = 'row'+r;
      rw2.rownr = r;

      // alle Spalten reinhaengen
      var cn = self.row[r];
      for (var c=0;c<this.cols;c++) {
        if (!(c == self.selcol && self.selcolhidden)) {
          rw2.appendChild(createDiv(r, c, cn[c]));
        }
      }

      if (self.iconview) {
        if (cn[self.selcol] == self.selID) {
          setClass(rw2, 'rowsel');
        } else {
          setClass(rw2, 'row');
        }
        if (r==0) {rw2.style.clear='both';}
      } else {
        rw2.style.clear='both';
        rw2.style.width = '100%';
      }

      ig.appendChild(rw2);
    }
    self.sorted=false;
  };

  // Refresh
  this.restyle = function() {

    if (self.iconview) {

      for (var r=0;r<self.rows;r++) {
        var rw = document.getElementById('row'+r);
        if (self.row[r][self.selcol] == self.selID ) {
          setClass(rw, 'rowsel');
        } else {
          setClass(rw, 'row');
        }
      }

    } else {

      for (var r=0;r<self.rows;r++) {
        for (var c=0;c<self.cols;c++) {
          var cell = document.getElementById("r"+r+"c"+c);
          if (cell !== null) {
            cell.style.width = self.colwidth[c];
            if (self.row[r][self.selcol] == self.selID ) {
              setClass(cell, 'cellsel');
            } else {
              setClass(cell, (r%2==0)?'cell2':'cell' );
            }
          }
        }
      }

    } // ende Normal
  };

  this.cvsexport = function() {
    var msg='';
    // Reiheninhalte exportieren
    for (var r=0;r<self.rows;r++) {
      for (var c=0;c<self.cols;c++) {
        msg += "\""+self.row[r][c]+"\";";
      }
      msg+="\n";
    }
    alert (msg);
  };

  // ---------------------------------------------
  // Events
  // ---------------------------------------------

  // Headlines Highlight
  this.headHighlight = function(ev) {
    var e = getEvent(ev);
    var t = e.targ; if (!t) return;
    setClass(t, "headersel");
  };

  this.headNormal = function(ev) {
    var e = getEvent(ev);
    var t = e.targ; if (!t) return;
    setClass(t, "header");
  };

  // Selection aendert sich
  this.selevent = function(ev) {
    var e = getEvent(ev);
    var t = e.targ; if (!t) return;
    if (t.rownr > self.rows) return;
    if (self.row[t.rownr] === null || self.row[t.rownr] === undefined) return;
    var newID = self.row[t.rownr][self.selcol];
    if (newID != self.selID && newID !== null && newID !== undefined) {
      self.selID = newID
      self.restyle();
      self.selChange();
    }
  };

  this.selChange = function() {
    // User-Event
  };

  this.dblclick = function(ev) {
    // alert ("Selected ID: " + self.selID);
  };

  // Spaltenweises sortieren
  this.columnSort = function(ev) {
    var e = getEvent(ev);
    var t = e.targ; if (!t) return;

    // Flip Sortierung
    if (t.sortDir <= 0) { t.sortDir = 1; } else { t.sortDir = 0; }

    // Pfeile
    if (self.oldsortcol && t != self.oldsortcol) {
      self.oldsortcol.style.backgroundImage="url('"+self.imgpath+"pix.gif')";
      self.oldsortcol.sortDir = 0;
    }
    t.style.backgroundImage="url('"+self.imgpath+((t.sortDir)?'asc.gif':'desc.gif')+"')";
    t.style.backgroundRepeat="no-repeat";
    t.style.backgroundPosition="right center";
    self.oldsortcol = t;

    self.sortgrid();

    return stopEvent(ev);
  };

  // Spaltenweises sortieren
  this.sortgrid = function() {
    // Inhalt neu sortieren
    sortcol = self.oldsortcol.colnr;
    if (self.rows >1) {
      self.row = self.row.sort((self.oldsortcol.sortDir)?compAsc:compDesc);

      // Refresh
      for (var r=0;r<self.rows;r++) {
        var cn = self.row[r];
        for (var c=0;c<self.cols;c++) {
          if (!(c == self.selcol && self.selcolhidden)) {
            if (cn[c] === null || cn[c] == '') {
              document.getElementById("r"+r+"c"+c).innerHTML = ' &nbsp;';
            } else {
              document.getElementById("r"+r+"c"+c).innerHTML = cn[c];
            }

          }
        }
      }
      self.restyle();
      self.sorted=true;
    }
  };

/**
 * Resize Funktionen
 */

  this.startResize = function(ev){
    var e = getEvent(ev);

    var gr = document.getElementById((self.gridID));
    rowwidth = gr.offsetWidth+3;

    if (e.rightButton) {
      splitx = e.X;
      splitsz = e.targ.offsetWidth;

      e.targ['onmousedown']= null;
      e.targ['onmousemove']= self.doResize;
      e.targ['onmouseup']= self.endResize;
      e.targ['onlosecapture']= self.endResize;
      e.targ.style.cursor="e-resize";
      return stopEvent(ev);
    }

  };

  this.doResize = function(ev) {
    var e = getEvent(ev);
    var sz = splitsz + e.X - splitx;
    if (sz < 10) {sz = 10;}
    var gz = rowwidth + sz - splitsz;
    if (gz < rowwidth) {gz = rowwidth ;}

    var ig = document.getElementById((self.gridID)+'innergrid');
    if (ig) { ig.style.width = gz + 'px'; }
    e.targ.style.width = sz+'px';

    // e.targ = null;
    return stopEvent(ev);
  };

  this.endResize = function(ev){
    var e = getEvent(ev);
    var sz = splitsz + e.X - splitx;
    if (sz < 10) {sz = 10;}
    rowwidth = rowwidth + sz - splitsz;

    self.colwidth[e.targ.colnr]=sz;

    e.targ['onmousedown']= self.startResize;
    e.targ['onmousemove']= null;
    e.targ['onmouseup']= null;
    e.targ['onlosecapture']= null;
    e.targ.style.cursor="auto";

    self.restyle();

    return stopEvent(ev);
  };

  this.setXMLdata = function(obj){

    var rws = obj.getElementsByTagName('rows');

    // Noch nicht fertig
    for (var i=0;i<rws.length;i++)  {
      var cell=getTagVal(rws[i],'title');
    }

    if (self.sorted) {self.sortgrid();}
  };
}



// ----------------------------------------------------------------------------
// Kalender Control
// ----------------------------------------------------------------------------

// Global variables
CalControls = new Array();
CalMouseStatus = false;
var clickEventAssigned = false;

function AssignClickEvent() {
  // Callbacks for document.onclick
  if (!clickEventAssigned) {
    oldOnclick = document.onclick ? document.onclick : new Function;
    document.onclick = function ()  {
      if(!CalMouseStatus){
        for(i=0; i<CalControls.length; ++i){
          CalControls[i].hide();
        }
      }
      oldOnclick(arguments[0] ? arguments[0] : null);
    }
    clickEventAssigned = true;
  }
}

// -------------------
// Das Kalender-Objekt
// -------------------
function CalCtrl(calendarID, inputID) {
  var self = this;

  // Properties
  this.calendarID = calendarID;          // Div und Objectname
  this.inputID = inputID;                // Datums-Inputfeld
  this.imgpath = '../img/';              // Verzeichnis fuer Bilder

  // Datum
  this.today = new Date();
  this.date  = this.today.getDate();
  this.month = this.today.getMonth();
  this.year  = this.today.getFullYear();
  this.Zeitraum = 5;                      // 5 Jahre

  this.actMonat = this.month;
  this.actJahr = this.year;
  this.init = false;

  // Private Hilfsfunktion
  function mitnull(num) {
    return ((num <= 9) ? ("0" + num) : num);
  };

  // Anzeige des Kalender-Controls
  this.show = function() {
    var month, year, Monatsnamen, numdays, thisMonth, firstOfMonth;
    var ret, row, i, cssClass, linkHTML, Monat, Jahr;
    var prev, next, monthCombo, dummy, yearCombo, html;

    this.actMonat = month = arguments[0] != null ? arguments[0] : this.actMonat;
    this.actJahr  = year  = arguments[1] != null ? arguments[1] : this.actJahr;

    Monatsnamen = new Array('Januar', 'Februar', 'M&auml;rz', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember');
    numdays = this.monatstage(month, year);

    thisMonth    = new Date(year, month, 1);
    firstOfMonth = thisMonth.getDay();

    // First few blanks up to first day
    ret = new Array(new Array());
    for(i=0; i<firstOfMonth; i++){
      ret[0][ret[0].length] = '<td>&nbsp;</td>';
    }

    // Main body of calendar
    row = 0;
    i   = 1;
    while(i <= numdays){
      if(ret[row].length == 7){
        ret[++row] = new Array();
      }

      //  Generate this cells' HTML
      cssClass = (i == this.date && month == this.month && year == this.year) ? 'cal_today' : 'cal_day';
      linkHTML = '<a class="cal_ref" href="javascript: ' + this.calendarID + '.setdate(' + i + ', ' + (Number(month) + 1) + ', ' + year + ');">' + i++ + '</a>';

      ret[row][ret[row].length] = '<td align="center" class="' + cssClass + '">' + linkHTML + '</td>';
    }

    // Format the HTML
    for(i=0; i<ret.length; i++){
      ret[i] = ret[i].join('\n') + '\n';
    }

    // Vorheriger Monat
    Jahr  = thisMonth.getFullYear();
    Monat = thisMonth.getMonth() - 1;
    if(Monat < 0){
      Monat = 11;
      Jahr--;
    }
    prev = '<a class="cal_ref" href="javascript: ' + this.calendarID + '.show(' + Monat + ', ' + Jahr + ')">';
    prev += '<img src="' + this.imgpath + 'prev.gif" alt="<<" border="0" /></a>';

    // Naechster Monat
    Jahr  = thisMonth.getFullYear();
    Monat = thisMonth.getMonth() + 1;
    if(Monat > 11){
      Monat = 0;
      Jahr++;
    }
    next = '<a class="cal_ref" href="javascript: ' + this.calendarID + '.show(' + Monat + ', ' + Jahr + ')">';
    next += '<img src="' + this.imgpath + 'next.gif" alt=">>" border="0" /></a>';

    // Monats-Combo
    dummy = '';
    for (i=0; i<12; i++) {
      selected = (i == thisMonth.getMonth() ? 'selected="selected"' : '');
      dummy += '<option value="' + i + '" ' + selected + '>' + Monatsnamen[i] + '</option>';
    }
    monthCombo = '<select class="cal_combo" name="months" onchange="' + this.calendarID + '.show(this.options[this.selectedIndex].value, ' + this.calendarID + '.actJahr)">' + dummy + '</select>';

    // Jahres-Combo
    dummy = '';
    for (i = thisMonth.getFullYear() - this.Zeitraum; i <= (thisMonth.getFullYear() + this.Zeitraum); i++) {
      selected = (i == thisMonth.getFullYear() ? 'selected="selected"' : '');
      dummy += '<option value="' + i + '" ' + selected + '>' + i + '</option>';
    }
    yearCombo = '<select class="cal_combo" name="years" onchange="' + this.calendarID + '.show(' + this.calendarID + '.actMonat, this.options[this.selectedIndex].value)">' + dummy + '</select>';

    html = '<table cellpadding="0" cellspacing="0" class="cal_table">';
    html += '<tr><td colspan="7" class="cal_header">' + prev +'&nbsp;'+ monthCombo +'&nbsp;'+ yearCombo +'&nbsp;'+ next + '</td>';
    html += '</tr>\n<tr>';
    html += '<td class="cal_dayname">So</td>';
    html += '<td class="cal_dayname">Mo</td>';
    html += '<td class="cal_dayname">Di</td>';
    html += '<td class="cal_dayname">Mi</td>';
    html += '<td class="cal_dayname">Do</td>';
    html += '<td class="cal_dayname">Fr</td>';
    html += '<td class="cal_dayname">Sa</td></tr>';
    html += '<tr>' + ret.join('</tr>\n<tr>') + '</tr>';
    html += '</table>';

    var elcal = document.getElementById(this.calendarID);
    elcal.innerHTML = html;

    if (!arguments[0] && !arguments[1]) {
      var elinp = document.getElementById(this.inputID);
      elcal.style.top  = (elinp.offsetTop + elinp.offsetHeight + 1) + 'px';
      elcal.style.left = elinp.offsetLeft + 'px';
      elcal.style.visibility = 'visible';
    }
  };

  // ich bin dann mal weg...
  this.hide = function() {
    document.getElementById(this.calendarID).style.visibility = 'hidden';
  };

  // Tage eines Monats
  this.monatstage = function(month, year) {
    monthdays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
    if (month != 1) {
      return monthdays[month];
    } else {
       return ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0 ? 29 : 28);
    }
  };

  // Evtl. mit privater Callback
  this.setdate = function (date, month, year) {
    //document.getElementById(this.inputID).value = mitnull(date) + '.' + mitnull(month) + '.' + year;
    document.getElementById(this.inputID).value = year + '-' + mitnull(month) + '-' + mitnull(date);
    document.getElementById(this.calendarID).style.visibility = 'hidden';
  };

  this.mouseover = function (status) {
    CalMouseStatus = status;
    return true;
  };

  // Constructor
  if (this.init ==false) {
    this.init ==true;
    CalControls[CalControls.length] = this;
    AssignClickEvent();
  }
}


