/**
  *  Class: Common
  */
var Common = new Class({
    decodeNum: function(i) {
        var i = i+'';
            i = i.replace(/,/, '.');
            i = parseFloat(i);
            
        return i;
    },

    encodeNum: function(i, n) {
        var n = n  ?  n  :  2;
        
        var i = i+'';
            i = i.replace(/,/, '.');
            i = parseFloat(i);
            i = i.toFixed(n);
            i = i+'';
            i = i.replace(/\./, ',');

        return i;
    },
    
    multiplicate: function(number, multiplier) {
        return this.decodeNum(number.value) * this.decodeNum(multiplier.value);
    }
});


/**
  *  Class: Startup
  */
var Startup = new Class({
    initialize: function() {
        new Request.JSON({
            url: RKA_CALLBACK_SCRIPT+'?command=startup&t='+Date.parse(Date())
        }).get();
    }
});


/**
  *  Class: Templates
  *
  *  @param  object  obj  Collection of DOM-Elements
  */
var Templates = new Class({
    initialize: function(obj) {
        this.form    = obj.form;
        this.img     = obj.img;

        this.cont_id = 'templates';

        this.addListener();
    },

    addListener: function() {
        this.img.addEvent('click', this.getTemplates.bind(this));
    },

    getTemplates: function() {
        new Request.JSON({
            url:        RKA_CALLBACK_SCRIPT+'?command=get_templates&t='+Date.parse(Date()),
            onComplete: this.Layer.bind(this)
        }).get();
    },

    Layer: function(data) {
        if (data.length > 0) {
            this.buildLayer(data);
        }
        else {
            if ($(this.cont_id)) {
                $(this.cont_id).dispose();
            }
            else {
                alert('Keine Vorlagen vorhanden.');
            }
        }
    },

    buildLayer: function(data) {
        if ($(this.cont_id)) {
            $(this.cont_id).dispose();
        }

        var coords = this.img.getCoordinates();

        var cont   = new Element('div', {
            'id':     this.cont_id,
            'class':  'layer',
            'styles': {
                'position': 'absolute',
                'top':      (coords.top + coords.height) + 'px',
                'left':     coords.left + 'px'
            }
        });
        
        cont.injectInside($$("body")[0]);

        for (var a = 0; a < data.length; a++)
        {
            var text = data[a].name;

            var span = new Element('span', {
                'html':   text,
                'events': {
                    'click': this.setDefault.bind(this, data[a])
                }
            });

            var img  = new Element('img', {
                'src':    RKA_IMG_PATH+'del.png',
                'title':  'Vorlage loeschen',
                'events': {
                    'click': this.deleteEntry.bind(this, data[a])
                }
            });

            var clear = new Element('div', { 'class': 'clear' });

            var row  = this.newRow(cont, [span, img, clear], { 'class': 'entry' });
        }
    
        var row = this.newRow(cont, 'Schliessen', { 'class': 'closeBtn' });
        row.addEvent('click', this.closeLayer.bind(this));
    },

    newRow: function(parent, data, attr) {
        var row = new Element('p');

        if ($type(data) == 'array') {
            for (var a = 0; a < data.length; a++) {
                data[a].injectInside(row);
            }
        }
        else if ($type(data) == 'element') {
            data.injectInside(row);
        }
        else if ($type(data) == 'string') {
            row.set('html', data);
        }
        
        row.injectInside(parent);

        if (attr) {
            if (attr['class']) {
                row.addClass(attr['class']);
            }
        }

        return row;
    },

    closeLayer: function() {
        if ($(this.cont_id)) {
            $(this.cont_id).dispose();
        }
    },

    setDefault: function(data) {
        for (var a in data) {
            if (this.form[a])
            {
                data[a] = !$type(data[a])  ?  ""  :  data[a];

                this.form[a].value = data[a];
            }
            this.closeLayer();
        }
    },

    deleteEntry: function(data) {
        var check = confirm('Soll die Vorlage wirklich geloescht werden?')

        if (check)
        {
            new Request({
                url: RKA_CALLBACK_SCRIPT+'?command=del_template&t='+Date.parse(Date()),
                onComplete: (function(){
                    this.getTemplates();
                }).bind(this)
            }).get(data);
        }
    }
});


/**
  *  Class: dateFormat
  *
  *  @param  object  elem  DOM-Element (INPUT)
  */
var dateFormat = new Class({
    initialize: function(elem) {
        if (this.valid(elem))
        {
            this.elem = elem;
            this.addListener();
        }
    },

    addListener: function() {
        this.elem.onfocus = function() {
            openCalendar(this.elem);
        }.bind(this);
    },

    valid: function(elem) {
        return (elem  &&  elem.tagName == 'INPUT');
    }
});


/**
  *  Class: timeFormat
  *
  *  @params  object  elem_hour  DOM-Element (SELECT) of hour
  *  @params  object  elem_minute  DOM-Element (SELECT) of minute
  */
var timeFormat = new Class({
    initialize: function(elem_hour, elem_minute, default_time) {
        if (this.valid(elem_hour)  &&  this.valid(elem_minute))
        {
            this.elem_hour    = elem_hour;
            this.elem_minute  = elem_minute;
            this.default_time = (default_time)  ?  default_time  :  false;

            this.fillHour();
            this.fillMinute();
        }
    },

    fillHour: function() {
        for (var hour = 0; hour < 24; hour++) {
            option           = document.createElement('option');
            option.value     = hour;
            option.innerHTML = (hour < 10)  ?  '0'+hour  :  hour;
            option.selected  = (this.default_time  &&  this.default_time.h == hour);
            
            this.elem_hour.appendChild(option);
        }
    },

    fillMinute: function() {
        for (var minute = 0; minute < 60; minute += 10) {
            option           = document.createElement('option');
            option.value     = minute;
            option.innerHTML = (minute < 10)  ?  '0'+minute  : minute;
            option.selected  = (this.default_time  &&  this.default_time.m == minute);
            
            this.elem_minute.appendChild(option);
        }
    },

    valid: function(elem) {
        return (elem  &&  elem.tagName == 'SELECT');
    }
});


/**
  *  Class: Duration
  *
  *  @param  object  obj  Collection of DOM-Elements (INPUT)
  */
var Duration = new Class({
    initialize: function(obj) {
        this.start         = obj.start;
        this.end           = obj.end;
        this.accommodation = obj.accommodation;
        this.catering      = obj.catering;

        this.addListener();
    },

    addListener: function() {
        var start_date    = this.start.date;
        var start_hour    = this.start.hour;
        var start_minute  = this.start.minute;
        var end_date      = this.end.date;
        var end_hour      = this.end.hour;
        var end_minute    = this.end.minute;

        // Standardwerte fuer die Uhrzeiten
        var default_time  = new Array();
        [start_hour, start_minute, end_hour, end_minute].each(function(elem){
            default_time[elem.name] = elem.value;
        });

        // Reisebeginn
        [start_date, start_hour, start_minute].each(function(elem){
            switch (elem.tagName)
            {
                case 'INPUT':
                    elem.addEvent('blur', (function(event){
                        if (!this.checkdate(start_date, start_hour, start_minute, end_date, end_hour, end_minute)) {
                            alert('Reisebeginn kann nicht groesser als Reiseende sein.');
                            elem.value = '';
                        }
                    }).bind(this));
                break;

                case 'SELECT':
                    elem.addEvent('change', (function(event){
                        if (!this.checkdate(start_date, start_hour, start_minute, end_date, end_hour, end_minute)) {
                            alert('Reisebeginn kann nicht groesser als Reiseende sein.');
                            elem.value = default_time[elem.name];
                        }
                    }).bind(this));
                break;
            }
        }, this);
        
        // Reiseende
        [end_date, end_hour, end_minute].each(function(elem){
            switch (elem.tagName)
            {
                case 'INPUT':
                    elem.addEvent('blur', (function(event){
                        if (!this.checkdate(start_date, start_hour, start_minute, end_date, end_hour, end_minute)) {
                            alert('Reiseende kann nicht kleiner als Reisebeginn sein.');
                            elem.value = '';
                        }
                    }).bind(this));
                break;

                case 'SELECT':
                    elem.addEvent('change', (function(event){
                        if (!this.checkdate(start_date, start_hour, start_minute, end_date, end_hour, end_minute)) {
                            alert('Reiseende kann nicht kleiner als Reisebeginn sein.');
                            elem.value = default_time[elem.name];
                        }
                    }).bind(this));
                break;
            }
        }, this);
    },

    checkdate: function(start_date, start_hour, start_minute, end_date, end_hour, end_minute) {
        if ($chk(start_date.value)  &&  $chk(end_date.value)  &&  $chk(start_hour.value)  &&  $chk(start_minute.value)  &&  $chk(end_hour.value)  &&  $chk(end_minute.value))
        {
            var start_time = this.getTimestamp(start_date, start_hour, start_minute);
            var end_time   = this.getTimestamp(end_date, end_hour, end_minute);

            if (start_time > end_time) {
                return false;
            }
           
            this.Duration(start_time, end_time);
        }
        
        return true;
    },

    Duration: function(start, end) {
        var duration   = { firstDay: '', between: '', lastDay: '' };

        // Unix-Timestamps
        start_unix     = start / 1000;
        end_unix       = end / 1000;

        // Datum
        var start  = new Date(start);
        var end    = new Date(end);
        start_date = start.getDate() + '.' + (start.getMonth() + 1) + '.' + start.getFullYear();
        end_date   = end.getDate()   + '.' + (end.getMonth()   + 1) + '.' + end.getFullYear();

        switch (start_date == end_date)
        {
            // Am gleichen Tag
            case true:
                duration.firstDay = this.getInterval(end_unix - start_unix);
            break;

            // Verschiedene Tage
            case false:
                // Erster Tag
                var end_of_start   = new Date(start.getFullYear(), start.getMonth(), start.getDate(), 24, 0, 0);
                end_of_start       = end_of_start.getTime() / 1000;
                duration.firstDay  = this.getInterval(end_of_start - start_unix);

                // Letzter Tag
                var start_of_end   = new Date(end.getFullYear(), end.getMonth(), end.getDate(), 0, 0, 0);
                start_of_end       = start_of_end.getTime() / 1000;
                duration.lastDay   = this.getInterval(end_unix - start_of_end);

                // Volle Tage (Zwischenzeit)
                var between        = (end_unix - start_unix) - ((end_of_start - start_unix) + (end_unix - start_of_end));
                duration.between   = (between > 0)  ?  this.getInterval(between)  :  '';
            break;
        }

        this.setAccommodation(duration);
        this.catering.setDuration(duration);
    },

    setAccommodation: function(obj) {
        this.resetAccommodation();

        if (obj.between  &&  obj.between.days) {
            this.accommodation.value = obj.between.days;
            this.accommodation.fireEvent('accommodation_fill');
        }
    },

    resetAccommodation: function() {
        this.accommodation.value = 0;
        this.accommodation.fireEvent('accommodation_fill');
    },

    getInterval: function(seconds) {
        var days          = parseInt(seconds / (60 * 60 * 24));
        seconds          -= parseInt(days * (60 * 60 * 24));

        var hours         = parseInt(seconds / (60 * 60));
        seconds          -= parseInt(hours * (60 * 60));
        
        var minutes       = parseInt(seconds / 60);
        seconds          -= parseInt(minutes * 60);

        var interval      = { 'days': days, 'hours': hours, 'minutes': minutes };
        
        return interval;
    },

    humanInterval: function(obj) {
        var interval = '';
        var time     = [obj.days, 'Tage', obj.hours, 'Stunden', obj.minutes, 'Minuten'];
        
        for (var a = 0; a < time.length; a += 2) {
            if (time[a] == 1) {
                interval += time[a] + ' ' + time[a+1].substr(0, (time[a+1].length - 1)) + ' ';
            }
            else if (time[a] > 1) {
                interval += time[a] + ' ' + time[a+1] + ' ';
            }
        }

        return interval;
    },

    getCharge: function(interval, charge) {
        if (interval  &&  charge)
        {
            switch (interval.days > 0)
            {
                // Erster oder letzter Tag
                case false:
                    for (var a in charge) {
                        for (var hour = charge[a].time[0]; hour <= charge[a].time[1]; hour++) {
                            if (interval.hours == hour) {
                                return charge[a].amount;
                            }
                        }
                    }
                break;

                // Volle Tage
                case true:
                    return (interval.days * charge.amount);
                break;
            }
        }
    },

    getTimestamp: function(date, hour, minute) {
        date   = date.value.split(".");
        hour   = hour.value;
        minute = minute.value;
        
        date   = new Date(date[2], (date[1] - 1), date[0], hour, minute, 0);
        date   = date.getTime();

        return date;
    }
});


/**
  *  Class: Address
  *
  *  @param  object  elem  Collection of DOM-Elements (INPUT)
  */
var Address = new Class({
    initialize: function(elem) {
        this.elem           = elem;
        this.search         = false;
        this.min_length     = 1;
        this.suggs          = false;
        this.timer          = false;
        this.timeout        = 0.5;
        
        this.addListener();
    },

    addListener: function() {
        this.elem.onkeyup = this.startTimer.bind(this);
    },

    startTimer: function() {
        if (!this.timer)
        {
            this.timer = this.searchAddress.delay((this.timeout * 1000), this);
        }
        else
        {
            this.stopTimer();
            this.startTimer();
        }
    },

    stopTimer: function() {
        if (this.timer)
        {
            $clear(this.timer);
            this.timer = false;
        }
    },

    searchAddress: function() {
        this.search = this.elem.value.trim();
        
        if (this.search.length >= this.min_length)
        {
            new Request.JSON({
                url: RKA_CALLBACK_SCRIPT+'?command=get_adresses&t='+Date.parse(Date()),
                method: 'get',
                onSuccess: this.displayLayer.bind(this)
            }).send('search='+this.search);
        }
        else
        {
            this.closeLayer();
        }
    },

    displayLayer: function(data) {
        this.stopTimer();

        if (data.length > 0)
        {
            if (!this.suggs)
            {
                var coords = this.elem.getCoordinates();
                suggs      = new Element('div', {
                    'class':  'layer',
                    'styles': {
                        'position':         'absolute',
                        'top':              (coords.top + coords.height) + 'px',
                        'left':             coords.left + 'px',
                        'width':            coords.width + 'px'
                    }
                });
                
                suggs.injectInside(document.body);
                
                this.suggs = suggs;
            }
            else
            {
                this.suggs.empty();
            }
            
            data.each(this.newEntry, this);
            this.closeBtn();
            
            window.suggs_layer_display = true;
        }
        else
        {
            if (this.suggs) {
                this.closeLayer();
            }
        }
    },

    newEntry: function(data) {
        var text       = data.trim();
        var text_clear = text;
        
        var reg        = new RegExp('(' + this.search + ')', 'ig'); reg.exec(text);
        text           = text.replace(reg, '<b>' + RegExp.$1 + '</b>')
        
        row            = this.newRow(this.suggs, text, { 'class': 'entry' });
        
        row.addEvent('click', this.fillSearch.bind(this, row));
    },

    newRow: function(parent, text, attr) {
        var row = new Element('p');

        row.set('html', text);
        row.injectInside(parent);

        if (attr) {
            if (attr['class']) {
                row.addClass(attr['class']);
            }
        }

        return row;
    },

    closeBtn: function() {
        var row = this.newRow(this.suggs, 'Schliessen', { 'class': 'closeBtn' });
        row.addEvent('click', this.closeLayer.bind(this));
    },

    fillSearch: function(a) {
        this.elem.focus();
        this.elem.value = a.get("text");
        this.closeLayer();
        
        this.elem.fireEvent('fill');
    },

    closeLayer: function() {
        if (this.suggs) {
            this.suggs.dispose();
            this.suggs                 = false;
            window.suggs_layer_display = false;
        }
    }
});


/**
  *  Class: Direction
  *
  *  @param  object  obj  Collection of DOM-Elements (INPUT)
  */
var Direction = new Class({
    initialize: function(obj) {
        this.start_elem = obj.start;
        this.end_elem   = obj.end;
        this.roundtrip  = obj.roundtrip;
        this.direction  = obj.direction;
        this.TDI        = obj.TDI;
        this.stopover   = false;

        this.setDefaults();
        this.setReadonly();
        this.addListener();
    },

    setDefaults: function() {
        this.direction.value = '0,00';
    },

    setReadonly: function() {
        this.direction.set('readonly', true);
    },

    addListener: function() {
        [this.start_elem, this.end_elem].each(function(elem){
            elem.addEvents({
                'fill': this.Direction.bind(this),
                'blur': this.Direction.bind(this)
            });
        }, this);
    },

    Direction: function(e) {
        this.getDirection();
    },

    getDirection: function() {
        var start_val = this.start_elem.value.trim();
        var end_val   = this.end_elem.value.trim();
        
        if ($chk(start_val)  &&  $chk(end_val)  &&  !$chk(window.suggs_layer_display))
        {
            this.start_elem.blur();
            this.end_elem.blur();

            GMap_Directions(start_val, end_val, this.setDirection.bind(this));
        }
    },

    setDirection: function(directions) {
        if (directions)
        {
            var val = ((this.roundtrip.checked)  ?  ((directions.meters / 1000) * 2)  :  directions.meters / 1000).toFixed(2).replace(/\./, ',');
            this.direction.set('value', val);
        }


        console.log(2);
        this.TDI.setDirection();
        console.log(3);
    }
});


/**
  *  Class: Roundtrip
  *
  *  @param  object  obj  Collection of DOM-Elements (INPUT)
  */
var Roundtrip = new Class({
    initialize: function(obj) {
        this.checkbox  = obj.checkbox;
        this.direction = obj.direction;
        this.TDI       = obj.TDI;

        this.addListener();
    },

    addListener: function() {
        this.checkbox.addEvent((Browser.Engine.gecko  ?  "change"  :  "click"), this.updateDirection.bind(this));
    },

    updateDirection: function() {
        var checked = this.checkbox.checked;
        var val     = this.direction.value.trim();

        if (val) {
            val = val.replace(/,/, '.');
            val = (checked)  ?  (val * 2)  :  (val / 2);
            val = val.toFixed(2);
            val = (val + '').replace(/\./, ',');
            
            this.direction.value = val;
        }

        this.TDI.setDirection();
    }
});


/**
  *  Class: DetourDirection
  *
  *  @param  object  obj  Collection of DOM-Elements
  */
var DetourDirection = new Class({
    Implements: Common,
    initialize: function(obj) {
        this.element = obj.direction;
        this.TDI     = obj.TDI;

        this.active  = false;
        this.oldval  = '';

        this.setDefault();
        this.addListener();
    },

    setDefault: function() {
        this.element.value = '0,00';
    },

    addListener: function() {
        this.element.addEvents({
            'focus': this.clearValue.bind(this),
            'blur':  this.checkValue.bind(this)
        });
    },

    clearValue: function() {
        if (!this.active)
        {
            this.active        = true;
            this.oldval        = this.element.value;
            this.element.value = '';
        }
    },

    checkValue: function() {
        if (this.active)
        {
            if (this.element.value.test(/^(\d+[,.]?\d+|\d+)$/)) {
                this.element.value = this.encodeNum(this.element.value);
            }
            else {
                this.element.value = this.oldval;
            }

            this.TDI.setDirection();

            this.active = false;
        }
    }
});


/**
  *  Class: CateringCharge
  *
  *  @param  object  obj  Collection of DOM-Elements
  */
var CateringCharge = new Class({
    Implements: Common,
    initialize: function(obj) {
        this.duration = false;
        this.total    = obj.total;
        this.main_row = $('travel_charge');
        this.row_id   = 'travel_charge_row';
        this.htr_id   = {
            'travel':        'travel_charge',
            'accommodation': 'accommodation'
        };
        this.counter  = 0;
        this.charges  = {
            'firstDay': {
                'title': 'Erster Tag',
                'data': {
                    '1': {
                        'time': [8, 14],
                        'amount': 6.00
                    },
                    '2': {
                        'time': [14, 24],
                        'amount': 12.00
                    }
                }
            },
            'between': {
                'title': 'Volle Tage',
                'amount': 24.00
            },
            'lastDay': {
                'title': 'Letzter Tag',
                'data': {
                    '1': {
                        'time': [8, 14],
                        'amount': 6.00
                    },
                    '2': {
                        'time': [14, 24],
                        'amount': 12.00
                    }
                }
            }
        };

        this.setDefaults();
        this.setReadonly();
    },

    displayRows: function(id) {
        document.getElements('tr[id^='+id+']').each(function(elem){
            elem.removeClass('hidden');
        });
    },

    hiddenRows: function() {
        for (var a in this.htr_id) {
            document.getElements('tr[id^='+this.htr_id[a]+']').each(function(elem){
                if (!elem.hasClass('hidden')) {
                    elem.addClass('hidden');
                }
            });
        }
    },

    setDefaults: function() {
        this.total.value = '0,00';
    },

    setReadonly: function() {
        this.total.readonly = true;
    },

    setDuration: function(obj) {
        this.duration = obj;
        
        this.hiddenRows();
        
        this.clear();
        this.genTable();
    },

    genTable: function() {
        var total = 0;

        // Erster Tag
        if ($chk(this.duration.firstDay))
        {
            var firstDay   = this.charges.firstDay;
            var title      = firstDay.title;
            var days       = 0;
            var hours      = ((this.duration.firstDay.hours == 0)  &&  (this.duration.firstDay.days > 0))  ?  24  :  this.duration.firstDay.hours;
            
            for (var a in firstDay.data)
            {
                var curr_d_data  = firstDay.data[a];

                var days         = (!$chk(days)  ||  days == 0)  ?  (this.inArray(curr_d_data.time, hours)  ?  1  :  0)  :  0;
                var amount       = ((days > 0)  ?  curr_d_data.amount  :  0);

                if (days == 0) {
                    continue;
                }

                var input_name   = 'catering_firstday_'+a+'_';

                this.addRow([
                    {
                        //'html': this.genInput(input_name+'text', title + ' (' + curr_d_data.time[0] + ' bis ' + curr_d_data.time[1] + ' Stunden)', { 'class': 'camou' }),
                        'html': title + ' (' + curr_d_data.time[0] + ' bis ' + curr_d_data.time[1] + ' Stunden)',
                        'attr': { 'class': 'title' }
                    },
                    {
                        'html': this.genInput(input_name+'days', days) + ' Tag(e)',
                        'attr': { 'class': 'days' }
                    },
                    {
                        'html': 'a ' + this.genInput(input_name+'amount', this.encodeNum(curr_d_data.amount)) + ' &euro;',
                        'attr': { 'class': 'amount' }
                    },
                    {
                        'html': this.genInput(input_name+'total', this.encodeNum(amount)) + ' &euro;',
                        'attr': { 'class': 'amount' }
                    }
                ]);

                total += amount;               
                title  = '';
            
                this.displayRows(this.htr_id.travel);
            }
        }
        
        // Volle Tage
        if ($chk(this.duration.between))
        {
            var c_between    = this.charges.between;
            var days         = this.duration.between.days;
            var title        = c_between.title;
            var amount       = days * c_between.amount;

            var input_name   = 'catering_between_';

            this.addRow([
                {
                    //'html': this.genInput(input_name+'text', title, { 'class': 'camou' }),
                    'html': title,
                    'attr': { 'class': 'title' }
                },
                {
                    'html': this.genInput(input_name+'days', days) + ' Tag(e)',
                    'attr': { 'class': 'days' }
                },
                {
                    'html': 'a ' + this.genInput(input_name+'amount', this.encodeNum(c_between.amount)) + ' &euro;',
                    'attr': { 'class': 'amount' }
                },
                {
                    'html': this.genInput(input_name+'total', this.encodeNum(amount)) + ' &euro;',
                    'attr': { 'class': 'amount' }
                }
            ]);

            total += amount;
            
            this.displayRows(this.htr_id.travel);            
            this.displayRows(this.htr_id.accommodation);            
        }
        
        // Letzter Tag
        if ($chk(this.duration.lastDay))
        {
            var lastDay = this.charges.lastDay;
            var title   = lastDay.title;
            var days    = 0;
            var hours   = ((this.duration.lastDay.hours == 0)  &&  (this.duration.lastDay.days > 0))  ?  24  :  this.duration.lastDay.hours;
            
            for (var a in lastDay.data)
            {
                var curr_d_data  = lastDay.data[a];
                
                var days         = (!$chk(days)  ||  days == 0)  ?  (this.inArray(curr_d_data.time, hours)  ?  1  :  0)  :  0;
                var amount       = ((days > 0)  ?  curr_d_data.amount  :  0);
                
                if (days == 0) {
                    continue;
                }

                var input_name   = 'catering_lastday_'+a+'_';

                this.addRow([
                    {
                        //'html': this.genInput(input_name+'text', title + ' (' + curr_d_data.time[0] + ' bis ' + curr_d_data.time[1] + ' Stunden)', { 'class': 'camou' }),
                        'html': title + ' (' + curr_d_data.time[0] + ' bis ' + curr_d_data.time[1] + ' Stunden)',
                        'attr': { 'class': 'title' }
                    },
                    {
                        'html': this.genInput(input_name+'days', days) + ' Tag(e)',
                        'attr': { 'class': 'days' }
                    },
                    {
                        'html': 'a ' + this.genInput(input_name+'amount', this.encodeNum(curr_d_data.amount)) + ' &euro;',
                        'attr': { 'class': 'amount' }
                    },
                    {
                        'html': this.genInput(input_name+'total', this.encodeNum(amount)) + ' &euro;',
                        'attr': { 'class': 'amount' }
                    }
                ]);
                
                total += amount;
                title = '';
                
                this.displayRows(this.htr_id.travel);
            }
        }

        // Gesamtbetrag
        this.total.value = this.encodeNum(total);

        this.total.fireEvent('total_fill');
    },

    addRow: function(data) {
        var row = new Element('tr');
        row.set('id', this.row_id+(this.counter));
        
        var tr = (this.counter == 0)  ?  this.main_row  :  $(this.row_id+(this.counter-1));
        row.injectAfter(tr);
        
        data.each(function(d){
            this.addCell(row, d.html, d.attr);
        }, this);
        
        this.counter++;
    },

    addCell: function(row, html, attr) {
        var cell = new Element('td');
        cell.set('html', html);

        if (attr) {
            if (attr['class']) {
                cell.addClass(attr['class']);
            }
            if (attr['colspan']) {
                cell.setProperty('colspan', attr['colspan']);
            }
        }

        cell.injectInside(row);
    },

    genInput: function(name, value, attr) {
        var attr   = attr || {};

        var type   = attr.type   ?  attr.type   :  'text';
        var sclass = attr['class']  ?  attr['class']  :  'small right';

        var input  = '<input class="'+sclass+'" type="'+type+'" name="'+name+'" value="'+value+'" readonly />';

        return input;
    },

    clear: function() {
        var elements = $$("body")[0].getElements('tr[id^='+this.row_id+']');

        if (elements.length > 0) {
            elements.each(function(elem){
                elem.dispose();
            });
        }

        this.counter = 0;
    },

    inArray: function(stack, hour) {
        for (var a = stack[0]; a <= stack[1]; a++) {
            if (hour == a) {
                return true;
            }
        }
    }
});


/**
  *  Class: AccommodationCharge
  *
  *  @param  object  obj  Collection of DOM-Elements (INPUT)
  */
var AccommodationCharge = new Class({
    Implements: Common,
    initialize: function(obj) {
        this.item_bf  = obj.item_bf;
        this.item     = obj.item;
        this.flatrate = obj.flatrate;
        this.total    = obj.total;
        
        this.active = false;
        this.oldval;

        this.setReadonly();
        this.setDefaults();
        this.addListener();
    },

    setReadonly: function() {
        var elements = [
            this.flatrate.days,
            this.flatrate.amount,
            this.flatrate.total,
            this.item_bf.total,
            this.item.total,
            this.total
        ];

        elements.each(function(elem){
            elem.set('readonly', true);
        }, this);
    },

    setDefaults: function() {
        // Tage
        [this.item_bf.days, this.item.days, this.flatrate.days].each(function(elem){
            elem.value = '0';
        });
        
        // Summen
        [this.item_bf.total, this.item.total, this.flatrate.total, this.total].each(function(elem){
            elem.value = '0,00';
        });
        
        // Betraege
        [this.item_bf.amount, this.item.amount].each(function(elem){
            elem.value = '2,00';
        });
        
        this.flatrate.amount.value = '20,00';
    },

    addListener: function() {
        // Pauschale
        this.flatrate.days.addEvent('accommodation_fill', (function(){
            this.setSubTotal(this.multiplicate(this.flatrate.days, this.flatrate.amount), this.flatrate.total);
            this.setTotal();
        }).bind(this));

        // Tage und Betraege
        [this.item_bf,this.item].each(function(elem){
            elem.days.addEvents({
                'focus': this.days_focus.bind(this, elem),
                'blur':  this.days_blur.bind(this, elem)
            });
            elem.amount.addEvents({
                'focus': this.amount_focus.bind(this, elem),
                'blur':  this.amount_blur.bind(this, elem)
            });
        }, this);
    },

    days_focus: function(elements) {
        if (!this.active)
        {
            this.oldval         = elements.days.value.toInt();
            elements.days.value = '';
            this.active         = true;
        }
    },

    amount_focus: function(elements) {
        if (!this.active)
        {
            this.oldval           = elements.amount.value;
            elements.amount.value = '';
            this.active           = true;
        }
    },

    days_blur: function(elements) {
        if (this.active)
        {
            var val_el      = elements.days.value.toInt();
            var val_fr      = this.flatrate.days.value.toInt();

            if (val_el <= (val_fr + this.oldval))
            {
                this.flatrate.days.value  = val_fr + this.oldval;
                this.flatrate.days.value -= val_el;
                elements.days.value       = elements.days.value.toInt();
            }
            else
            {
                elements.days.value = this.oldval;
            }
            
            
            this.flatrate.days.fireEvent('accommodation_fill');

            this.setSubTotal(this.multiplicate(elements.days, elements.amount), elements.total);
            this.setTotal();
            
            this.active = false;
        }
    },

    amount_blur: function(elements) {
        if (this.active)
        {
            var val_el = elements.amount.value;

            if (val_el.test(/(\d+[,.]\d+|\d+)/)) {
                elements.amount.value = this.encodeNum(val_el);
            }
            else {
                elements.amount.value = this.oldval;
            }
            
            this.setSubTotal(this.multiplicate(elements.days, elements.amount), elements.total);
            this.setTotal();
            
            this.active = false;
        }
    },

    setSubTotal: function(val, total) {
        total.value = this.encodeNum(val);
    },

    setTotal: function() {
        var item_bf_total  = this.decodeNum(this.item_bf.total.value);
        var item_total     = this.decodeNum(this.item.total.value);
        var flatrate_total = this.decodeNum(this.flatrate.total.value);

        this.total.value   = this.encodeNum(item_bf_total + item_total + flatrate_total);

        this.total.fireEvent('total_fill');
    }
});


/**
  *  Class: TransportDirection
  *
  *  @param  object  obj  Collection of DOM-Elements
  */
var TransportDirection = new Class({
    Implements: Common,
    initialize: function(obj) {
        this.travel    = obj.travel;
        this.detour    = obj.detour;
        this.transport = obj.transport;
    },

    setDirection: function() {
        var val              = (this.decodeNum(this.travel.value) + this.decodeNum(this.detour.value));
        this.transport.value = this.encodeNum(val);

        this.finish();
    },

    finish: function() {
        this.transport.fireEvent('transport_fill');
    }
});


/**
  *  Class: TransportCharge
  *
  *  @param  object  obj  Collection of DOM-Elements
  */
var TransportCharge = new Class({
    Implements: Common,
    initialize: function(obj) {
        this.car    = obj.car;
        this.train  = obj.train;
        this.taxi   = obj.taxi;
        this.plane  = obj.plane;
        this.misc   = obj.misc;
        this.total  = obj.total;

        this.active = false;
        this.oldval = '';

        this.setDefaults();
        this.setReadonly();
        this.addListener();
    },

    setReadonly: function() {
        var elements = [
            this.car.total,
            this.total
        ];
        
        elements.each(function(elem){
            elem.set('readonly', true);
        });
    },

    setDefaults: function() {
        [this.car.direction, this.car.total, this.train, this.taxi, this.plane, this.misc, this.total].each(function(elem){
            elem.value = '0,00';
        });
        this.car.amount.value = '0,30';
    },

    addListener: function() {
        this.car.direction.addEvent('transport_fill', (function(){
            this.setCarTotal();
            this.setTotal();
        }).bind(this));
        
        [this.car.direction, this.car.amount, this.train, this.taxi, this.plane, this.misc].each(function(elem){
            elem.addEvents({
                'click': this.clearValue.bind(this, elem),
                'blur':  this.checkValue.bind(this, elem)
            });
        }, this);
    },

    clearValue: function(elem) {
        if (!this.active)
        {
            this.active     = true;
            this.oldval     = elem.value;
            elem.value = '';
        }
    },

    checkValue: function(elem) {
        if (this.active)
        {
            if (elem.value.test(/^(\d+[,.]?\d+|\d+)$/)) {
                elem.value = this.encodeNum(elem.value);
            }
            else {
                elem.value = this.oldval;
            }

            this.active = false;
        }

        this.setCarTotal();
        this.setTotal();
    },

    setCarTotal: function() {
        this.car.total.value = this.encodeNum(this.multiplicate(this.car.direction, this.car.amount));
    },

    setTotal: function() {
        var car          = this.decodeNum(this.car.total.value);
        var train        = this.decodeNum(this.train.value);
        var taxi         = this.decodeNum(this.taxi.value);
        var plane        = this.decodeNum(this.plane.value);
        var misc         = this.decodeNum(this.misc.value);

        this.total.value = this.encodeNum(car + train + taxi + plane + misc);

        this.total.fireEvent('total_fill');
    }
});


/**
  *  Class: MiscCharge
  *
  *  @param  object  obj  Collection of DOM-Elements
  */
var MiscCharge = new Class({
    Implements: Common,
    initialize: function(obj) {
        this.semi   = obj.semi;
        this.custom = obj.custom;
        this.total  = obj.total;

        this.setDefaults();
        this.setReadonly();
        this.addListener();
    },

    setDefaults: function() {
        var elements = [this.semi, this.total].combine(this.custom);

        elements.each(function(elem){
            elem.value = '0,00';
        });
    },

    setReadonly: function() {
        this.total.set('readonly', true);
    },

    addListener: function() {
        var elements = [this.semi].combine(this.custom);
        
        elements.each(function(elem) {
            elem.addEvents({
                'click': this.clearValue.bind(this, elem),
                'blur':  this.checkValue.bind(this, elem)
            });
        }, this);
    },

    clearValue: function(elem) {
        if (!this.active)
        {
            this.active     = true;
            this.oldval     = elem.value;
            elem.value = '';
        }
    },

    checkValue: function(elem) {
        if (this.active)
        {
            if (elem.value.test(/^(\d+[,.]?\d+|\d+)$/)) {
                elem.value = this.encodeNum(elem.value);
            }
            else {
                elem.value = this.oldval;
            }

            this.active = false;
        }

        this.setTotal();
    },

    setTotal: function() {
        var semi   = this.decodeNum(this.semi.value);
        var custom = 0;
        this.custom.each(function(elem){
            custom += this.decodeNum(elem.value);
        }, this);

        this.total.value = this.encodeNum(semi + custom);

        this.total.fireEvent('total_fill');
    }
});


/**
  *  Class: TotalCharge
  *
  *  @param  object  obj  Collection of DOM-Elements
  */
var TotalCharge = new Class({
    Implements: Common,
    initialize: function(obj) {
        this.catering      = obj.catering;
        this.accommodation = obj.accommodation;
        this.transport     = obj.transport;
        this.misc          = obj.misc;
        this.total         = obj.total;

        this.setDefaults();
        this.setReadonly();
        this.addListener();
    },

    setDefaults: function() {
        this.total.value = '0,00';
    },

    setReadonly: function() {
        this.total.set('readonly', true);
    },

    addListener: function() {
        [this.catering, this.accommodation, this.transport, this.misc].each(function(elem){
            elem.addEvent('total_fill', this.setTotal.bind(this));
        }, this);
    },

    setTotal: function() {
        var catering      = this.decodeNum(this.catering.value);
        var accommodation = this.decodeNum(this.accommodation.value);
        var transport     = this.decodeNum(this.transport.value);
        var misc          = this.decodeNum(this.misc.value);

        this.total.value  = this.encodeNum(catering + accommodation + transport + misc);
    }
});


/**
  *  Class: SaveButton
  *
  *  @param  element  element  DOM-Element (INPUT)
  */
var SaveButton = new Class({
    initialize: function(element) {
        this.element = element;

        this.addListener();
    },
    
    addListener: function() {
        this.element.addEvent('click', this.saveAction.bind(this));
    },

    saveAction: function() {
        var button = this.element;
        
        var oldval = button.value;
        
        button.set({
            'value':    'Bitte warten...',
            'disabled': true
        });

        new Request({
            url:        RKA_CALLBACK_SCRIPT+'?command=save&t='+Date.parse(Date()),
            method:     'post',
            onComplete: function() {
                alert('Daten wurden gespeichert.');
                
                button.set({
                    'value':    oldval,
                    'disabled': false
                });
            }
        }).send(button.form);
    }
});


/**
  *  Class: PrintButton
  *
  *  @param  element  element  DOM-Element (INPUT)
  */
var PrintButton = new Class({
    initialize: function(element) {
        this.element = element;

        this.addListener();
    },

    addListener: function() {
        this.element.addEvent('click', this.print.bind(this));
    },

    print: function() {
        window.print();
    }
});
