//if(!CJS)
{
  var CJS =
  {
    Class : function(members)
            {
              var fn = function()
              {
                if(arguments[0] != 'no_init')
                {
                  return this.init.apply(this, arguments);
                }
              }
              fn.prototype = members;
              AJS.update(fn, CJS.Class.prototype);
              return fn;
            }
  };

  CJS.Class.prototype =
  {
    extend : function(members)
    {
      var parent = new this('no_init');
      for(k in members)
      {
        var prev = parent[k];
        var cur = members[k];
        if (prev && prev != cur && typeof cur == 'function')
        {
          cur = this._parentize(cur, prev);
        }
        parent[k] = cur;
      }
      return new CJS.Class(parent);
    },

    implement : function(members)
    {
      AJS.update(this.prototype, members);
    },

    _parentize : function(cur, prev)
    {
      return function()
      {
        this.parent = prev;
        return cur.apply(this, arguments);
      }
    }
  };

  CJS.time = new CJS.Class({
      name : "unbekannt",
      owner : null,
      stunde : 0,
      minute : 0,

      init : function(options)
      {
        AJS.update(this, options);
      },

      dbg : function()
      {
        var s = "[" + this.name + "] " + this.toString();

        if (this.owner && this.owner.out)
          this.owner.out(s);
        else if (this.owner && this.owner.cb_out)
          this.owner.cb_out(s);
        else
          alert(s);
      },

      now : function()
      {
        this.fromDate(new Date());
      },

      clone : function()
      {
        return new CJS.time({ stunde : this.stunde,
                              minute : this.minute,
                              name : this.name,
                              owner : this.owner
                            });
      },

      getTimeInMinutes : function()
      {
        return this.stunde*60 + this.minute;
      },

      setTimeInMinutes : function(n)
      {
        this.stunde = Math.floor(n / 60);
        this.minute = n % 60;

        if (this.stunde > 23)
          this.stunde -= 24;
      },

      addMinutes : function (n)
      {
        this.setTimeInMinutes(this.getTimeInMinutes() + n);
      },

      set : function(t)
      {
        if (typeof t == "string")
          return this.fromString(t);
        else if (typeof t == "object")
        {
          if (t instanceof Date)
            this.fromDate(t);
          else if (t instanceof CJS.time)
          {
             this.stunde = t.stunde;
             this.minute = t.minute;
          }
          return true;
        }
        return false;
      },

      fromString : function (s)
      {
        var Suche =   /(\d{1,2})[:](\d{1,2})/
        var Ergebnis = Suche.exec(s);

        if (Ergebnis && Ergebnis.length >= 2)
        {
          this.stunde = parseInt(Ergebnis[1], 10);
          this.minute = parseInt(Ergebnis[2], 10);
        }
      },

      fromDate : function(d)
      {
        this.stunde = d.getHours();
        this.minute = d.getMinutes();
      },

      toString : function()
      {
        var h, m;

        if (this.stunde < 10)
          h = "0" + this.stunde;
        else
          h = this.stunde;

        if (this.minute < 10)
          m = "0" + this.minute;
        else
          m = this.minute;

        return h + ":" + m;
      },

      checkTime : function(s, seconds)
      {
        //(Schritt 1) Fehlerbehandlung
        s = s || this.toString();

        //(Schritt 2) Aufspaltung der Zeiteingabe
        s = s.split(":");
        if (s.length != 2 && (s.length != 3 || !seconds))
          return false;

        //(Schritt 3) Stunden checken
        if (!s[0].match(/^[ ]*[0-9]{1,2}[ ]*$/))
          return false;
        s[0] = parseInt(s[0], 10);
        if (s[0] < 0 || s[0] > 23)
          return false;

        //(Schritt 4) Minuten checken
        if (!s[1].match(/^[ ]*[0-9]{2}[ ]*$/))
          return false;
        s[1] = parseInt(s[1], 10);
        if (s[1] < 0 || s[1] > 59)
          return false;

        //(Schritt 5 optional) Sekunden checken
        if (s.length == 3)
        {
          if (!s[2].match(/^[ ]*[0-9]{2}[ ]*$/))
            return false;
          s[2] = parseInt(s[2], 10);
          if (s[2] < 0 || s[2] > 59)
            return false;
        }
        return true;
      },

      compare : function (t)
      {
        if (!t)
          return false;
        return this.toString() == this.toString(t) ? true : false;
      }
  });


  CJS.date = new CJS.Class({
      name : "unbekannt",
      owner : null,
      tag : 1,
      monat : 1,
      jahr : 1970,

      init : function(options)
      {
        AJS.update(this, options);
      },

      dbg : function()
      {
        var s = "[" + this.name + "] " + this.toString();

        if (this.owner && this.owner.out)
          this.owner.out(s);
        else if (this.owner && this.owner.cb_out)
          this.owner.cb_out(s);
        else
          alert(s);
      },

      checkDate : function(s)
      {
        //(Schritt 1) Fehlerbehandlung
        s = s || this.toString();

        //(Schritt 2) Aufspaltung des Datums
        s = s.split(".");
        if (s.length != 3)
          return false;

        //(Schritt 3) Entfernung der fuehrenden Nullen und Anpassung des Monats
        if (!s[0].match(/^[ ]*[0-9]{1,2}[ ]*$/))
          return false;
        s[0] = parseInt(s[0], 10);

        if (!s[1].match(/^[ ]*[0-9]{1,2}[ ]*$/))
          return false;
        s[1] = parseInt(s[1], 10)-1;

        //(Schritt 4) Behandlung Jahr nur zweistellig
        if (!s[2].match(/^[ ]*[0-9]{2}[ ]*$/) && !s[2].match(/^[ ]*[0-9]{4}[ ]*$/))
          return false;
        if (s[2].length == 2)
          s[2] = "20" + s[2];

        //(Schritt 5) Erzeugung eines neuen Dateobjektes
        var kontrolldatum = new Date(s[2], s[1], s[0]);

          //(Schritt 6) Vergleich, ob das eingegebene Datum gleich dem JS-Datum ist
        return (kontrolldatum.getDate()==s[0] && kontrolldatum.getMonth()==s[1] && kontrolldatum.getFullYear()==s[2]) ? true : false;
      },

      getDaysInMonth : function(d)
      {
        d = d || this.clone();
        d.tag = 1;
        if (++d.monat > 12)
        {
          d.monat = 1;
          d.jahr++;
        }
        d.prevDay();
        return d.tag;
      },

      today : function()
      {
        this.fromDate(new Date());
      },

      clone : function()
      {
        return new CJS.date({ jahr : this.jahr,
                              monat : this.monat,
                              tag : this.tag,
                              name : this.name,
                              owner : this.owner
                            });
      },

      nextDay : function ()
      {
        this.addDays(1);
      },

      prevDay : function ()
      {
        this.addDays(-1);
      },

      addDays : function (n)
      {
        var d = this.toDate();
        d.setTime(d.getTime() + n*86400000);
        this.fromDate(d)
      },

      dateDiff : function(d)
      {
        var d1 = this.toDate();
        var d2 = d.toDate();
        return Math.round((d2.getTime() - d1.getTime()) / 86400000);
      },

      set : function(d)
      {
        if (typeof d == "string")
          return this.fromString(d);
        else if (typeof d == "object")
        {
          if (d instanceof Date)
            this.fromDate(d);
          else if (d instanceof CJS.date)
          {
             this.jahr = d.jahr;
             this.monat = d.monat;
             this.tag = d.tag;
          }
          return true;
        }
        return false;
      },

      toDate : function()
      {
        return new Date(this.jahr, this.monat-1, this.tag);
      },

      fromDate : function(d)
      {
        this.jahr = d.getFullYear();
        this.monat = d.getMonth()+1; // monatszählung beginnt bei null
        this.tag = d.getDate();
      },

      toString : function(d)
      {
        if (d)
        {
          if (typeof d == "string")
          {
            var nd = new CJS.date;
            if (nd.fromString(d))
              return nd.toString();
          }
          else if (typeof d == "object")
          {
            if (d instanceof Date)
              return d.getDate() + "." + (d.getMonth()+1) + "." + d.getFullYear();
            else if (d instanceof CJS.date)
              return d.toString();
          }

          return "#error";
        }

        return this.tag + "." + this.monat + "." + this.jahr;
      },

      fromString : function (s)
      {
        //(Schritt 2) Aufspaltung des Datums
        s = s.split(".");
        if (s.length != 3)
          return false;

        //(Schritt 3) Entfernung der fuehrenden Nullen und Anpassung des Monats
        if (!s[0].match(/^[]*[0-9]{1,2}$/))
          return false;
        s[0] = parseInt(s[0], 10);

        if (!s[1].match(/[0-9]{1,2}/))
          return false;
        s[1] = parseInt(s[1], 10)-1;

        //(Schritt 4) Behandlung Jahr nur zweistellig
        if (s[2].length == 2)
          s[2] = "20" + s[2];

        //(Schritt 5) Erzeugung eines neuen Dateobjektes
        var kontrolldatum = new Date(s[2], s[1], s[0]);
        if (kontrolldatum.getDate()==s[0] && kontrolldatum.getMonth()==s[1] && kontrolldatum.getFullYear()==s[2])
        {
          this.fromDate(kontrolldatum);
          return true;
        }
        else
          return false;
      },

      compare : function (d)
      {
        if (!d)
          return false;
        return this.toString() == this.toString(d) ? true : false;
      }
  });
}

var TypeChecker =
{
  decorate : function(elm, typ, options)
  {
    if (typeof elm == 'string')
      elm = AJS.$(elm);

    if (!elm)
      return false;

    options = options || {};

    var checkDate = function()
    {
      if (!elm)
        return;

      var d = new CJS.date;
      if (d.checkDate(elm.value))
        AJS.setStyle(elm, "color", "#000");
      else
        AJS.setStyle(elm, "color", "#f00");
    };

    var checkTime = function()
    {
      if (!elm)
        return;

      var t = new CJS.time;
      if (t.checkTime(elm.value, options.seconds))
        AJS.setStyle(elm, "color", "#000");
      else
        AJS.setStyle(elm, "color", "#f00");
    };

    var checkNumber = function()
    {
      if (!elm)
        return;

      //(Schritt 3) Zahlen checken
      if (elm.value.match(/^[ ]*[-]?[0-9]+[ ]*$/))
        AJS.setStyle(elm, "color", "#000");
      else
        AJS.setStyle(elm, "color", "#f00");
    };

    var me = this;
    switch (typ)
    {
      case "date":
        AJS.addEventListener(elm, "keyup", function () { checkDate(); });
        break;

      case "time":
        AJS.addEventListener(elm, "keyup", function () { checkTime(); });
        break;

      case "number":
        AJS.addEventListener(elm, "keyup", function () { checkNumber(); });
        break;

      default:
        break;
    }
  }
}
