/**
 * DB Bahn JavaScript
 * Copyright (c) 2008, namics (deutschland) gmbh. All rights reserved.
 * Code licensed under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 * */

/* Konfigurationsfunktion fuer alle Kalender.
   Muss hier ausserhalb des Namespaces stehen! */
function qfInitCalendars() {
    var ms = jQuery('input#qf-months-texts').val();
    var ma = "";
    if (ms) {
        ma = ms.split(",");
    }

    var ws = jQuery('input#qf-weekday-texts-short').val();
    var wa = "";
    if (ws) {
        wa = ws.split(",");
    }

    var cs = jQuery('input#qf-cal-close-text').val();

    calman.config = {
        "today"           : new Date(),
        "viewPeriodS"     : parseUserDateInput("01.01.1900"),
        "viewPeriodE"     : parseUserDateInput("31.12.2099"),
        "dataPeriodS"     : parseUserDateInput("01.01.1900"),
        "dataPeriodE"     : parseUserDateInput("31.12.2099"),
        "monthsTexts"     : ma,
        "weekdaysTexts"   : wa,
        "closeText"       : cs,
        "showShortYear"   : true,
        "styleClass"      : "calendardiv"
    }
}

var BAHN_QF_CNL = {
	qfReiseprofilChangedEvent: 'qfReiseprofilChangedEvent', // anderes Reiseprofil in Selectbox ausgewaehlt

    QF_MAX_REISENDE: 5,             // max. Anzahl Reisende fuer Quickfinder

    QF_REISENDER_TYP_ERW: "E",      // Reisendertyp Erwachsener
    QF_REISENDER_TYP_FKIND: "F",    // Reisendertyp Familienkind (Kind reist zus. mit mind. 1 Erwachsenem)
    QF_REISENDER_TYP_AKIND: "K",    // Reisendertyp alleinreisendes Kind
    QF_REISENDER_TYP_KKIND: "B",    // Reisendertyp Kleinkind

    // Konstanten fuer QfReisendeUpdater:
    // Keys fuer IDs der Selectboxen
    QF_KEY_ADULTS_ID: 1,
    QF_KEY_CHILDREN_ID: 2,
    QF_KEY_INFANTS_ID: 3,
    // Keys fuer Praefixe fuer die IDs der Inputfelder in den Reisendenzeilen
    QF_KEY_PREFIX_TRAV_TYPE_ID: 4,
    QF_KEY_PREFIX_TRAV_BC_ID: 5,
    QF_KEY_PREFIX_TRAV_AGE_ID: 6,
    QF_KEY_PREFIX_TRAV_BDAY_ID: 7,
    // Key fuer ID des Containers fuer Reisendendaten im Non-Javascript-Fall
    QF_KEY_TRAVS_CONT_ID: 8,
    // Key fuer ID des Containers fuer Reisendendaten im Javascript-Fall
    QF_KEY_TRAVS_JS_CONT_ID: 9,
    // Key fuer Praefix fuer die IDs der Reisendenzeilen
    QF_KEY_PREFIX_TRAV_ROWS: 10,

    // gibt an, ob es sich um den Quickfinder im Webclient handelt 
    // (andernfalls handelt es sich um den Standalone-QF im www.bahn.de-Content)
    qfWebclient: false,

    // Initialize quickfinder
	init: function() {
		// Quickfinder CNL
		BAHN_QF_CNL.initQuickfinderCNL();
		
		// allgemeine Kalenderkonfigurationen
		qfInitCalendars();
		
		// felder mit defaultweren fuellen
		BAHN_QF_CNL.qfInitDateAndTime();
		
		// Automatismen fuer Reisenden-Felder
		var params = new Object();
		// IDs der Reisende-Anzahl-Selectboxen
		params[BAHN_QF_CNL.QF_KEY_ADULTS_ID] = 'qf-adult-number';
		params[BAHN_QF_CNL.QF_KEY_CHILDREN_ID] = 'qf-children-number';
		params[BAHN_QF_CNL.QF_KEY_INFANTS_ID] = 'qf-infant-number';
		// Praefixe fuer die IDs der Inputfelder in den Reisendenzeilen
		params[BAHN_QF_CNL.QF_KEY_PREFIX_TRAV_TYPE_ID] = 'qf-trav-type-';
		params[BAHN_QF_CNL.QF_KEY_PREFIX_TRAV_BC_ID] = 'qf-trav-bc-';
		params[BAHN_QF_CNL.QF_KEY_PREFIX_TRAV_AGE_ID] = 'qf-trav-age-';
		params[BAHN_QF_CNL.QF_KEY_PREFIX_TRAV_BDAY_ID] = 'qf-trav-bday-';
		// ID des Containers fuer Reisendendaten im Non-Javascript-Fall
		params[BAHN_QF_CNL.QF_KEY_TRAVS_CONT_ID] = 'qf-travs';
		// ID des Containers fuer Reisendendaten im Javascript-Fall
		params[BAHN_QF_CNL.QF_KEY_TRAVS_JS_CONT_ID] = 'qf-travs-js';
		// Praefix fuer die IDs der Reisendenzeilen
		params[BAHN_QF_CNL.QF_KEY_PREFIX_TRAV_ROWS] = 'qf-travrow-';
		new BAHN_QF_CNL.QfReisendeUpdater(params);
	},

	initQuickfinderCNL: function() {
		jQuery( '#quickfinder-cnl ul.tablist a' ).click( function(ev) {
			ev.preventDefault();
			jQuery( '#quickfinder-cnl div.wrapper' ).toggleClass( 'with-linklist' );
			jQuery( '#qf-cnl-content' ).toggle();
		} );
	},
	
	// ergaenzt falls noetig fuer Datumsteile (z. B. Tag oder Monat, als Zahl!) eine fuehrende Null
    // und liefert Ergebnis als String zurueck
    qfDatePartStr: function(datePart) {
        return (datePart < 10) ? ("0" + datePart) : datePart;
    },

    // Datums- und Uhrzeitfelder mit Default-Werten befuellen
    qfInitDateAndTime: function() {
       // aktuelles Datum und Zeit
        var now = new Date();
        var sNowDate = BAHN_QF_CNL.qfDatePartStr(now.getDate())
                + "." + BAHN_QF_CNL.qfDatePartStr(now.getMonth() + 1)
                + "." + now.getFullYear();
        var sNowTime = BAHN_QF_CNL.qfDatePartStr(now.getHours())
                + ":" + BAHN_QF_CNL.qfDatePartStr(now.getMinutes());

        // morgen
        var tomorrow = new Date();
        tomorrow.setDate(tomorrow.getDate() + 1);
        var sTomDate = BAHN_QF_CNL.qfDatePartStr(tomorrow.getDate())
                + "." + BAHN_QF_CNL.qfDatePartStr(tomorrow.getMonth() + 1)
                + "." + tomorrow.getFullYear();

        // Uebermorgen
        var tomorrow2 = new Date();
        tomorrow2.setDate(tomorrow2.getDate() + 2);
        var sTom2Date = BAHN_QF_CNL.qfDatePartStr(tomorrow2.getDate())
                + "." + BAHN_QF_CNL.qfDatePartStr(tomorrow2.getMonth() + 1)
                + "." + tomorrow2.getFullYear();

        // Felder nur vorbelegen, wenn noch nichts drinsteht!
        // (andernfalls wurden sie z. B. aus dem Buchungsprofil des Kunden bereits befuellt)
        var field;

        field = jQuery('#qf-departure-date');
        if (field.val().length == 0) {
        	field.val(sNowDate);
        }
        field = jQuery('#qf-time');
        if (field.val().length == 0) {
            field.val(sNowTime);
        }
    },
    
    /**
     * Diese Klasse behandelt die Events fuer und von den Reisenden-Anzahl-Selectboxen
     * und fuer die Reisendenzeilen (Typ + BC-Ermaessigung).
     * Reiseprofil ausgewaehlt:
     *  - Anpassen der angezeigten Anzahlen und max. Optionen der Reisenden-Anzahl-Selectboxen
     *  - Anzeigen der Daten der Reisenden in den Reisendenzeilen (z. B. Typ und Ermaessigung (=BC))
     * Reisendenanzahl geaendert:
     *  - max. auswaehlbaren Optionen der anderen Selectboxen veraendern sich, wenn die Auswahl einer Selectbox geaendert wird
     *  - entsprechend der Auswahl der Reisendenanzahl und -Typen werden Zeilen fuer die BC-Ermaessigung hinzu-/weggeblendet
     *
     * Parameter ist ein Array von HTML-Element-IDs bzw. ID-Praefixes.
     * Als Keys fuer Befuellung des Arrays muessen die BAHN_QF_CNL.QF_XYZ-Konstanten verwendet werden!
     */
    QfReisendeUpdater: function(params) {
        // Extensions fuer die IDs der Tag-/Monat-/Jahr-Einzelfelder fuer Geburtstag
        var TRAV_BDAY_DAY_EXT = "_day";
        var TRAV_BDAY_MONTH_EXT = "_month";
        var TRAV_BDAY_YEAR_EXT = "_year";

        // Selectboxen
        var adultsBox = document.getElementById(params[BAHN_QF_CNL.QF_KEY_ADULTS_ID]);
        var childrenBox = document.getElementById(params[BAHN_QF_CNL.QF_KEY_CHILDREN_ID]);
        var infantsBox = document.getElementById(params[BAHN_QF_CNL.QF_KEY_INFANTS_ID]);

        /**
         * Aktualisiert die Optionen der (Anzahl-)Selectbox, wobei die maximale Anzahl von Reisenden durch maxNumber bestimmt wird.
         */
        var updateMaxNumOptions = function(selectBox, maxNumber) {
            if (selectBox == null)
                return;

            var optionsSize = selectBox.options.length;
            var selIndex = selectBox.selectedIndex;

            var firstOptVal = parseInt((optionsSize > 0 ? selectBox.options[0].value : 0));
            var lastOptVal = parseInt((optionsSize > 0 ? selectBox.options[optionsSize - 1].value : 0));

            if (lastOptVal < maxNumber) {
                // stocke aktuelle Optionen auf die neue max. zulaessige Anzahl von Reisenden auf
                var option;
                for (var i = eval(lastOptVal + 1); i <= maxNumber; i++) {
                    option = document.createElement('option');
                    option.text = i;
                    option.value = i;
                    selectBox.options.add(option);
                }
            }
            else {
                // beschneide die Anzahl der Optionen auf die neue max. Anzahl
                selectBox.options.length = maxNumber + (firstOptVal == 0 ? 1 : 0);
            }

            // bisher selektierten Wert wieder selektieren (oder 1. Option, falls nicht moeglich)
            doSelectIndex(selectBox, selIndex);
        }
        
        /** 
         * Selektiert die Option mit dem uebergebenen Index, falls vorhanden.
         * Andernfalls wird die 1. Option selektiert.
         */
        var doSelectIndex = function(selectBox, selIndex) {
            if (selectBox == null)
                return;
        
            if (selIndex >= selectBox.options.length) {
                // falls der aktuell selektierte Index ausserhalb der Menge der Optionen liegt,
                // wird einfach die erste Option selektiert
                selectBox.selectedIndex = 0;
            }
            else {
                selectBox.selectedIndex = selIndex;
            }
        }

        /**
         * Aktualisiert die max. Anzahl von Optionen aller Anzahl-Selectboxen anhand der aktuell ausgewaehlten Werte
         * und div. Sonderregeln, so dass eine Gesamtzahl von BAHN_QF_CNL.QF_MAX_REISENDE nicht ueberschritten wird.
         */
        var updateNumberOfReisende = function(event) {
            var oTarget = BAHN.getTarget(event);

            // aktuell selektierte Werte der Selectboxen (zum spaeteren Rumrechnen unbedingt Ints draus machen!)
            var numAdults = parseInt(params[BAHN_QF_CNL.QF_KEY_ADULTS_ID].length > 0 && adultsBox != null ? adultsBox.value : 0);
            var numChildren = parseInt(params[BAHN_QF_CNL.QF_KEY_CHILDREN_ID].length > 0 && childrenBox != null ? childrenBox.value : 0);
            var numInfants = parseInt(params[BAHN_QF_CNL.QF_KEY_INFANTS_ID].length > 0 && infantsBox != null ? infantsBox.value : 0);

            // aktuell selektiert Indexe der Optionen
            // merken, da die aktuelle Auswahl aufgrund von Sonderregeln evtl. angepasst werden muss
            var idxAdults = parseInt(params[BAHN_QF_CNL.QF_KEY_ADULTS_ID].length > 0 && adultsBox != null ? adultsBox.selectedIndex : 0);
            var idxChildren = parseInt(params[BAHN_QF_CNL.QF_KEY_CHILDREN_ID].length > 0 && childrenBox != null ? childrenBox.selectedIndex : 0);
            var idxInfants = parseInt(params[BAHN_QF_CNL.QF_KEY_INFANTS_ID].length > 0 && infantsBox != null ? infantsBox.selectedIndex : 0);

            // Sonderregeln bei 0 Erwachsenen
            if (numAdults == 0) {
                // keine Kleinkinder moeglich
                numInfants = 0;
                if (infantsBox != null) {
                    idxInfants = 0; // Annahme: infantsBox beginnt immer mit Option 0 (Erw. beginnt bei Fiku mit 1!)
                }
                // hoechstens 1 alleinreisendes Kind moeglich
                if (numChildren > 1) {
                    numChildren = 1;
                    if (childrenBox != null) {
                        idxChildren = 1; // Annahme: childrenBox beginnt immer mit Option 0 (Erw. beginnt bei Fiku mit 1!)
                    }
                }
            }

            // Auswahl korrigieren, falls (jetzt) 0 Reisende ausgewaehlt sind
            var numTravs = numAdults + numChildren + numInfants;
            if (numTravs == 0) {
                // Erwachsene wurden gerade genullt
                if (oTarget.id === params[BAHN_QF_CNL.QF_KEY_ADULTS_ID]) {
                    if (childrenBox != null) {
                        // 1 Kind auswaehlen
                        idxChildren = 1;
                        numChildren = 1;
                    }
                // Kinder wurden gerade genullt
                } else if (oTarget.id === params[BAHN_QF_CNL.QF_KEY_CHILDREN_ID]) {
                    if (adultsBox != null) {
                        // 1 Erw. auswaehlen
                        idxAdults = 1;
                        numAdults = 1;
                    }
                }
            }

            // Sonderregeln bei 0 Erwachsenen
            if (numAdults == 0) {
                // moegliche Optionen der Selectboxen neu bestimmen
                updateMaxNumOptions(adultsBox, BAHN_QF_CNL.QF_MAX_REISENDE - numChildren - numInfants);
                updateMaxNumOptions(childrenBox, numChildren);
                updateMaxNumOptions(infantsBox, numInfants);
            }
            // mind. 1 Erwachsener
            else {
                // Max. Anzahl der Erwachsenen haengt von gewaehlter Anzahl Kinder und Kleinkinder ab.
                // Analog fuer die max. Anzahl Kinder und Kleinkinder.
                updateMaxNumOptions(adultsBox, BAHN_QF_CNL.QF_MAX_REISENDE - numChildren - numInfants);
                updateMaxNumOptions(childrenBox, BAHN_QF_CNL.QF_MAX_REISENDE - numAdults - numInfants);
                updateMaxNumOptions(infantsBox, BAHN_QF_CNL.QF_MAX_REISENDE - numAdults - numChildren);
            }
            
            // Richtige Option selektieren.
            // Entweder ist das die, die der Kunde aktuell ausgewaehlt hatte oder sie wurde aufgrund obiger Sonderregeln angepasst.
            // Der selectedIndex der Selectbox konnte aber oben noch nicht sofort angepasst werden,
            // da soviele Optionen evtl. (noch) nicht nur Verfuegung stehen.
            // Dies ist erst jetzt nach Anpassung der max. Optionen (updateMaxNumOptions()) der Fall.
            // Bsp: Waehle erst 5 Erw, danach 0 Erw.
            doSelectIndex(adultsBox, idxAdults);
            doSelectIndex(childrenBox, idxChildren);
            doSelectIndex(infantsBox, idxInfants);
        }

        /**
         * Liefert ein Array von QfReisender-Objekten mit den Daten der aktuell sichtbaren Reisendenzeilen
         */
        var getCurrentReisende = function() {
            var reisende = [];
            // iteriere ueber alle Reisendenrows ...
            for (var i = 1; i <= BAHN_QF_CNL.QF_MAX_REISENDE; i++) {
                // ... die sichtbar sind
                if (jQuery('#' + params[BAHN_QF_CNL.QF_KEY_PREFIX_TRAV_ROWS] + i).is(':visible')) {
                    // Reisender-Objekt mit den Daten der Felder der aktuellen Zeile fuellen
                    var r = new BAHN_QF_CNL.QfReisender();
                    r.typ = jQuery('#' + params[BAHN_QF_CNL.QF_KEY_PREFIX_TRAV_TYPE_ID] + i).val();
                    r.bahncard = jQuery('#' + params[BAHN_QF_CNL.QF_KEY_PREFIX_TRAV_BC_ID] + i).val();
                    r.geburtsdatum = jQuery('#' + params[BAHN_QF_CNL.QF_KEY_PREFIX_TRAV_BDAY_ID] + i).val();
                    r.geb_tag = jQuery('#' + params[BAHN_QF_CNL.QF_KEY_PREFIX_TRAV_BDAY_ID] + i + TRAV_BDAY_DAY_EXT).val();
                    r.geb_monat = jQuery('#' + params[BAHN_QF_CNL.QF_KEY_PREFIX_TRAV_BDAY_ID] + i + TRAV_BDAY_MONTH_EXT).val();
                    r.geb_jahr = jQuery('#' + params[BAHN_QF_CNL.QF_KEY_PREFIX_TRAV_BDAY_ID] + i + TRAV_BDAY_YEAR_EXT).val();
                    // Alter wird immer neu berechnet beim naechsten Anzeigen
                    reisende.push(r);
                }
            }
            return reisende;
        }

        /**
         * Aktualisiert anhand der Auswahl in den Anzahl-Selectboxen eine interne Liste von Reisenden (Model),
         * es werden leere neue Reisende des gewuenschten Typs hinzugefuegt oder die letzten jeden Typs entfernt.
         * Anhand dieser internen Reisendenliste wird die Oberflaeche aktualisiert.
         */
        var updateNumberOfReisendeRows = function() {
            // Daten der aktuell sichtbaren Reisendenzeilen ermitteln
            var reisende = getCurrentReisende();
            // aktuelle Reisende in typ-spez. Arrays aufteilen
            var adults = [];
            var children = [];
            var infants = [];
            for (var i = 0; i < reisende.length; i++) {
                var r = reisende[i];
                if (BAHN_QF_CNL.QF_REISENDER_TYP_ERW === r.typ) {
                    adults.push(r);
                } else if (BAHN_QF_CNL.QF_REISENDER_TYP_FKIND === r.typ || BAHN_QF_CNL.QF_REISENDER_TYP_AKIND === r.typ) {
                    children.push(r);
                } else if (BAHN_QF_CNL.QF_REISENDER_TYP_KKIND === r.typ) {
                    infants.push(r);
                }
            }

            // wg. Sonderregeln bei der Anzahl der Reisenden hat sich evtl. nicht nur die vom Kunden betaetigte Selectbox geaendert,
            // sondern auch die anderen Selectboxen - daher muss fuer alle Reisendentypen ueberprueft werden, ob Anpassungen noetig sind!
            var newReisende = [];
            var offset = 0;

            // Erwachsene
            if (adultsBox != null) {
                offset = adults.length - adultsBox.value;
                if (offset >= 0){
                    adults.length = adults.length - offset;
                } else {
                    newReisende = createNewReisende(Math.abs(offset), BAHN_QF_CNL.QF_REISENDER_TYP_ERW);
                    adults = adults.concat(newReisende);
                }
            }

            // Kinder
            if (childrenBox != null) {
                offset = children.length - childrenBox.value;
                if (offset >= 0){
                    children.length = children.length - offset;
                } else {
                    newReisende = createNewReisende(Math.abs(offset), BAHN_QF_CNL.QF_REISENDER_TYP_FKIND);
                    children = children.concat(newReisende);
                }
            }

            // Kleinkinder
            if (infantsBox != null) {
                offset = infants.length - infantsBox.value;
                if (offset >= 0){
                    infants.length = infants.length - offset;
                } else {
                    newReisende = createNewReisende(Math.abs(offset), BAHN_QF_CNL.QF_REISENDER_TYP_KKIND);
                    infants = infants.concat(newReisende);
                }
            }
            
            var resultReisende = [];
            resultReisende = resultReisende.concat(adults);
            resultReisende = resultReisende.concat(children);
            resultReisende = resultReisende.concat(infants);

            // Zeilen aktualisieren und de-/aktivieren
            updateReisendeRows(resultReisende);
        }

        /**
         * Erzeugt 'anzahl' Stueck neue Reisende vom uebergebenen Reisenden-Typ (eine der BAHN_QF_CNL.QF_REISENDER_TYP_XXX-Konstanten).
         */
        var createNewReisende = function(anzahl, typ) {
            var result = [];
            for (var j = 0; j < anzahl; j++){
                // neuer Reisender
                var r = new BAHN_QF_CNL.QfReisender();
                r.typ = typ;

                result.push(r);
            }
            return result;
        }

        /**
         * Fuellt die Daten der Reisenden in die ersten reisende.length Zeilen.
         * Die restlichen Zeilen werden ausgeblendet und ihre Input-Felder (inkl. Selectboxen etc.) disabled.
         *
         * Die Liste von Reisenden muss so aufgebaut sein,
         * dass jeweils alle Reisenden eines Typs direkt aufeinander folgen
         * und nicht Reisende anderen Typs dazwischenstehen.
         */
        var updateReisendeRows = function(reisende) {
            // Index fuer korrekte Nummerierung innerhalb der Reisendentypen im Label fuer die BC-Selectbox
            var labelIdx = 1;
            // Merker zum Feststellen von Typwechsel beim Iterieren
            var prevType = "";

            for (var i = 0; i < reisende.length; i++) {
                var r = reisende[i];
                // Indexes der Reisendenzeilen starten mit 1
                var j = eval(i + 1);
                // Reisendendaten in die Felder der i-ten Reisendenzeile fuellen
                jQuery('#' + params[BAHN_QF_CNL.QF_KEY_PREFIX_TRAV_TYPE_ID] + j).val(r.typ);
                jQuery('#' + params[BAHN_QF_CNL.QF_KEY_PREFIX_TRAV_BC_ID] + j).val(r.bahncard);
                jQuery('#' + params[BAHN_QF_CNL.QF_KEY_PREFIX_TRAV_BDAY_ID] + j).val(r.geburtsdatum);
                jQuery('#' + params[BAHN_QF_CNL.QF_KEY_PREFIX_TRAV_BDAY_ID] + j + TRAV_BDAY_DAY_EXT).val(r.geb_tag);
                jQuery('#' + params[BAHN_QF_CNL.QF_KEY_PREFIX_TRAV_BDAY_ID] + j + TRAV_BDAY_MONTH_EXT).val(r.geb_monat);
                jQuery('#' + params[BAHN_QF_CNL.QF_KEY_PREFIX_TRAV_BDAY_ID] + j + TRAV_BDAY_YEAR_EXT).val(r.geb_jahr);
                // Alter des Reisenden am Hinreisetag (immer neu berechnen)
                jQuery('#' + params[BAHN_QF_CNL.QF_KEY_PREFIX_TRAV_AGE_ID] + j).val(r.getAlter());

                // Nummerierung im Reisendenlabel bei neuem Typ zuruecksetzen
                if (prevType !== r.typ) {
                    labelIdx = 1;
                    prevType = r.typ;
                }
                // Labeltexte fuer die Reisendentypen kommen aus Hidden Fields "#<prefix-typ>name-<Typkuerzel>"
                var lblText = labelIdx + ". " + jQuery('#' + params[BAHN_QF_CNL.QF_KEY_PREFIX_TRAV_TYPE_ID] + 'name-' + r.typ).val();
                // Label fuer die BahnCard-Selectbox dem Reisendentyp anpassen
                jQuery("label[for='" + params[BAHN_QF_CNL.QF_KEY_PREFIX_TRAV_BC_ID] + j + "']").text(lblText);
                labelIdx++;
            }

            // die Zeilen mit den Reisendendaten sichtbar und aktiv schalten
            // (die uebrigen ausblenden/disablen)
            setReisendeRowsEnabled(1, reisende.length);

            BAHN.updateBuffer();
        }

        /**
         * Aktiviert die Reisendenzeilen im uebergebenen Intervall,
         * d. h. die Inputfelder werden enabled und die Zeile eingeblendet.
         * Die uebrigen werden deaktiviert (Inputfelder werden deaktiviert und Zeile ausgeblendet).
         * Der Startindex muss >= 1 sein wg. der Feld-/Zeilennamen.
         */
        var setReisendeRowsEnabled = function(startIdx, endIdx)  {
            // iteriere ueber alle Reisendenrows
            for (var i = 1; i <= BAHN_QF_CNL.QF_MAX_REISENDE; i++){
                // falls im uebergebenen Intervall
                if (startIdx <= i && i <= endIdx) {
                    // Inputfelder (input, select, ...) aktivieren
                    jQuery('#' + params[BAHN_QF_CNL.QF_KEY_PREFIX_TRAV_ROWS] + i + ' :input').removeAttr('disabled');
                    // Zeile einblenden
                    jQuery('#' + params[BAHN_QF_CNL.QF_KEY_PREFIX_TRAV_ROWS] + i).show()
                            .removeClass('hide'); // auch diese Class (aus HTML-Code) entfernen
                } else {
                    // Inputfelder (input, select, ...) deaktivieren
                    jQuery('#' + params[BAHN_QF_CNL.QF_KEY_PREFIX_TRAV_ROWS] + i + ' :input').attr('disabled', 'disabled');
                    // Zeile ausblenden
                    jQuery('#' + params[BAHN_QF_CNL.QF_KEY_PREFIX_TRAV_ROWS] + i).hide();
                }
            }
        }

        /**
         * Wenn eine der Reisenden-Anzahl-Selectboxen geaendert wurde,
         * die Selectboxen anpassen und auch die Reisendenzeilen.
         */
        var anzahlReisendeChanged = function(event) {
            // max. Optionen der Selectboxen anpassen
            updateNumberOfReisende(event);
            // Reisendenzeilen ein-/ausblenden
            updateNumberOfReisendeRows();
            // Info-Layers fuer Kind/Kleinkind schliessen
            jQuery('#quickfinder div.qf-number-desc a.closeButton').click();
        }

        /**
         * Wenn in der RProfil-Selectbox ein anderes Reiseprofil ausgewaehlt wurde,
         * die Daten des Reiseprofils im QF anzeigen
         * (Reisenden-Anzahl-Selectboxen und Reisendenzeilen).
         */
        var reiseprofilChanged = function(event, rprofil) {
            // Falls Kunde erst an den Anzahl-Selectboxen geaendert hat und dann ein Reiseprofil auswaehlt,
            // koennen ueber das Reiseprofil Reisendenanzahlen kommen, die momentan nicht in der Selectbox als Option enthalten sind 
            // (wg. automatisierter Beschraenkung auf max 5 Reisende insgesamt).
            // Daher hier jede Box auf die max. moegl. Reisendenzahl aufblaehen,
            // das wird danach in updateNumberOfReisende() wieder korrigiert.
            updateMaxNumOptions(adultsBox, BAHN_QF_CNL.QF_MAX_REISENDE);
            updateMaxNumOptions(childrenBox, BAHN_QF_CNL.QF_MAX_REISENDE);
            updateMaxNumOptions(infantsBox, BAHN_QF_CNL.QF_MAX_REISENDE);
            // neue Werte auswaehlen
            BAHN_QF_CNL.qfSelectByValue(adultsBox, rprofil.adults.length);
            BAHN_QF_CNL.qfSelectByValue(childrenBox, rprofil.children.length);
            BAHN_QF_CNL.qfSelectByValue(infantsBox, rprofil.infants.length);
            // max. moegliche Optionen der Selectboxen anhand der neuen Reisendenzahlen neu festlegen
            updateNumberOfReisende(event);

            // Reihenfolge der Reisendenzeilen festlegen: Erwachsene, Kinder, Kleinkinder
            var reisende = [];
            reisende = reisende.concat(rprofil.adults);
            reisende = reisende.concat(rprofil.children);
            reisende = reisende.concat(rprofil.infants);
            // Ermaessigungszeilen mit den Daten der Reisenden aus dem RProfil fuellen
            updateReisendeRows(reisende);
        }

        // Konstruktor 
        // (fuer Standalone-QF immer ausfuehren, fuer WEC-QF nur, wenn JS-Bereich sichtbar ist (d. h. *_dyn.css wurde nicht zurueckgerollt))
        if (BAHN_QF_CNL.qfWebclient === false || BAHNCONSISTENCY.isJsLoadedSuccessful) {
            // Input-Felder des Non-JS-Bereichs deaktivieren
            jQuery('#' +  params[BAHN_QF_CNL.QF_KEY_TRAVS_CONT_ID]  + ' :input').attr('disabled', 'disabled');
            // Input-Felder des JS-Bereichs aktivieren
            jQuery('#' +  params[BAHN_QF_CNL.QF_KEY_TRAVS_JS_CONT_ID]  + ' :input').removeAttr('disabled');
    
            // Reisende-Anzahl-Selectboxen aktivieren und Aenderungen belauschen.
            jQuery('#' + params[BAHN_QF_CNL.QF_KEY_ADULTS_ID])
                    .removeAttr('disabled')
                    .change(anzahlReisendeChanged);
            jQuery('#' + params[BAHN_QF_CNL.QF_KEY_CHILDREN_ID])
                    .removeAttr('disabled')
                    .change(anzahlReisendeChanged);
            jQuery('#' + params[BAHN_QF_CNL.QF_KEY_INFANTS_ID])
                    .removeAttr('disabled')
                    .change(anzahlReisendeChanged);
    
            // Die Erwachsenen-Selectbox ist im JS-Fall immer vorhanden,
            // sie stoesst stellvertretend fuer alle Selectboxen die Behandlung des qfReiseprofilChangedEvent an.
            // (Das Event gibts momentan nur im QF und soll auch nur dort behandelt werden - nicht z. B. auf MeineReiseprofil-Seite!
            // Falls das mal woanders auch verwendet werden soll, muss hier das Konzept geaendert werden:,
            // Die ID der sendenden Reiseprofilbox muss von ihr zusammen mit dem qfReiseprofilChangedEvent gesendet
            // und bei den Empfaengern beruecksichtigt werden, so dass nur die qfReiseprofilChangedEvents der eigenen RProfilbox verarbeitet werden.)
            if (params[BAHN_QF_CNL.QF_KEY_ADULTS_ID].substr(0, 3) == 'qf-') {
                jQuery('#' + params[BAHN_QF_CNL.QF_KEY_ADULTS_ID]).bind(BAHN_QF_CNL.qfReiseprofilChangedEvent, reiseprofilChanged);
            }
    
            // In HTML sind Werte fuer Anzahl Erwachsene/Kinder/Kleinkinder in den Selectboxen vorselektiert.
            // Daran die max. Optionen der Selectboxen sowie die Reisendenzeilen intial anpassen.
            anzahlReisendeChanged();
        }

        BAHN.updateBuffer();
    },
    
    /**
     * Die QfReisender-Klasse repraesentiert einen Reisenden.
     */
    QfReisender : function() {
        this.typ = "";
        this.bahncard = 0;
        this.geburtsdatum = "";
        // falls Geburtsdatum ueber Einzelfelder statt einem Feld angegeben wird
        // (fuer Auswertungen/Berechnungen (z. B. getAlter()) wird jedoch this.geburtsdatum verwendet!!)
        this.geb_tag = "";
        this.geb_monat = "";
        this.geb_jahr = "";

        /**
         * @return Alter des Reisenden am aktuellen Datum.
         *      Das Geburtsdatum muss im Format (d)d.(m)m.yyyy vorliegen.
         *      Falls diese Regeln verletzt sind, wird kein Alter, sondern "" (Leerstring) geliefert.
         */
        this.getAlter = function() {
            // Zieldatum wird in ordentlichem Format dd.mm.yyyy ins Cookie geschrieben,
            // sollte auch so hier ankommen
            if (!this.geburtsdatum || !this.geburtsdatum.length > 0 || this.geburtsdatum.length > 10) {
                return "";
            }
            var birthdate = new Date();
            // Geburtstag an "." aufsplitten, um Tag, Monat, Jahr zu erhalten
            var gdateElems = this.geburtsdatum.split(".");
            if (gdateElems.length === 3) {
                // new Date(y, m, d, ...), month in JS aus 0..11 !
                birthdate = new Date(gdateElems[2], gdateElems[1] - 1, gdateElems[0]);
            } else {
                return "";
            }
            var bday = birthdate.getDate();
            var bmonth = birthdate.getMonth();
            var byear = birthdate.getFullYear();

            var zieldate = new Date();
            var zday = zieldate.getDate();
            var zmonth = zieldate.getMonth();
            var zyear = zieldate.getFullYear();

            // Alter erstmal grob berechnen
            var age = zyear - byear;
            // Alterskorrektur in manchen Faellen
            if (zmonth < bmonth
                    || (zmonth === bmonth && zday < bday)) {
                age--;
            }
            if (age < 0) { // dann war Zieldatum < Geburtsdatum
                return "";
            } else {
                return age;
            }
        }
    }
};

jQuery(document).ready(function() {
	BAHN_QF_CNL.init();
});
