/*
    .------------------------------.
    |    Price calculator class    |
    *------------------------------*         
    
    Class: Price calculator
        Takes care of displaying and managing price calculator (Controller & View)
        
        Moreover, it sends and receives JSON packages.
        
    Requires:
        - <utility_functions.js> (needed by find_period_with_date)
        - <ware_class.js>
        - <school_demonstrator_class.js>
        
    Author: 
        Marko Ristin, Andreas Hermann
    
    Changelog:
        - 2007/01/27, mristin, initial version
        - 2007/07/30, ahermann, improved user interface, code refactoring
        - 2007/08/13, ahermann, reformatted comments for automatic documentation
        - 2007/08/28, ahermann, added dependency accommodation<->transfer
        - 2007/11/19, ahermann, added accommodation weeks, accommodation inscription fee, school material fee
*/

/**
 * 
 * @param {Object} a_school_demonstrator
 * @param {Object} prefetched_packages
 * @param {Int} country_id
 * @param {Int} city_id
 * @param {Int} school_id
 * @param {Date} today
 * @param {Object} url_fetch_obj
 */                                               

function Price_calculator ( a_school_demonstrator, 
                            prefetched_packages, 
                            country_id,  
                            city_id,      
                            school_id,
                            today,
                            url_fetch_obj )
{
    /*extern dojo, gettext */
    /*extern find_period_with_date, is_function, attach_hidden_field_to_form, xor, show_errors */
    /*extern copy_an_object */
    /*extern date_str_to_i18n_date, intersect_periods_of_owners, add_option_to_select_box, create_and_add_option_to_select_box */
    /*extern a_money_exchange, a_cart, a_wait_cursor_manager */
    /*extern Ware, Option */
    
    /* 
        Variable: url_fetch_obj
            URL for fetching objects
    */
    this.url_fetch_obj = null;

    /*    Properties:    */
    
    /*
        Variable: school_demonstrator
            Reference to the school_demonstrator
    */
    this.school_demonstrator = a_school_demonstrator;

    this.country = null;
    this.city = null;
    this.school = null;
    this.course = null;
    this.accommodation_form = null;
    
	this.country_set = null;
	this.city_set = null;
    this.school_set = null;
    this.course_set = null;
    this.accommodation_form_set = null;
    
    this.course_price_set = null;
    this.accommodation_price_set = null;
    this.school_inscription_fee_set = null;
    this.school_transfer_set = null;
    this.school_material_fee_set = null;
    
    this.course_season = null;
    this.price_periods = null;
    this.course_weeks = null;
    this.transfer = null;
    this.accommodation_weeks = null;
    
    this.total_price = null;

    this.form = dojoWrapper.getById('id_cart_form');

    /*    Interface elements:    */
    this.country_select_box = dojoWrapper.getById('id_price_calculator_select_country');
    this.city_select_box = dojoWrapper.getById('id_price_calculator_select_city');
    this.school_select_box = dojoWrapper.getById('id_price_calculator_select_school');
    this.course_select_box = dojoWrapper.getById('id_price_calculator_select_course');
    this.accommodation_form_select_box = dojoWrapper.getById('id_price_calculator_select_accommodation_form');
    this.transfer_select_box = dojoWrapper.getById('id_price_calculator_select_transfer');
    this.course_season_select_box = dojoWrapper.getById('id_price_calculator_select_course_season');
    this.course_weeks_select_box = dojoWrapper.getById('id_price_calculator_select_course_weeks');
    this.accommodation_weeks_select_box = dojoWrapper.getById('id_price_calculator_select_accommodation_weeks');
    this.price_period_span = dojoWrapper.getById('id_price_calculator_price_period_span');
    this.price_period_number_span = dojoWrapper.getById('id_price_calculator_price_period_number_span');
    this.locale_currency_select_box = dojoWrapper.getById('id_price_calculator_select_locale_currency');
    
    this.add_to_cart_button = dojoWrapper.getById('id_price_calculator_button_add_to_cart');
    this.book_button = dojoWrapper.getById('id_price_calculator_button_book');
    

    /*
        Prices fields:
    */
    this.span_course_price = dojoWrapper.getById('course_price_amount');
    this.span_course_price_currency = dojoWrapper.getById('course_price_currency');
    this.span_course_inscription_fee = dojoWrapper.getById('course_inscription_fee_amount');
	
	// New for yalea
	this.span_course_inscription_fee_currency = dojoWrapper.getById('course_inscription_fee_currency');
	
    this.span_course_inscription_fee_comment = dojoWrapper.getById('course_inscription_fee_comment');
    
    this.span_accommodation_price = dojoWrapper.getById('accommodation_price_amount');
    this.span_accommodation_price_currency = dojoWrapper.getById('accommodation_price_currency');
    this.span_accommodation_inscription_fee = dojoWrapper.getById('accommodation_inscription_fee_amount');
    this.span_accommodation_inscription_fee_comment = dojoWrapper.getById('accommodation_inscription_fee_comment');
    this.accommodation_price_row = dojoWrapper.getById('accommodation_price_row');
    
    this.span_transfer = dojoWrapper.getById('transfer_cost_amount');
    this.span_transfer_currency = dojoWrapper.getById('transfer_cost_currency');
    this.transfer_cost_row = dojoWrapper.getById('transfer_cost_row');
    
    this.span_school_material_fee_amount = dojoWrapper.getById('school_material_fee_amount');
    this.span_school_material_fee_currency = dojoWrapper.getById('school_material_fee_currency');
    this.school_material_fee_row = dojoWrapper.getById('school_material_fee_row');
    
    this.span_course_exam_fee_amount = dojoWrapper.getById('course_exam_fee_amount');
    this.span_course_exam_fee_currency = dojoWrapper.getById('course_exam_fee_currency');
    this.course_exam_fee_row = dojoWrapper.getById('course_exam_fee_row');
    
    this.span_total_price = dojoWrapper.getById('total_price');
    this.span_total_price_comment = dojoWrapper.getById('total_price_comment');
    this.span_total_price_currency = dojoWrapper.getById('total_price_currency');
    
    this.span_total_price_school_curr = dojoWrapper.getById('total_price_school_curr');
    this.span_total_price_school_curr_comment = dojoWrapper.getById('total_price_school_curr_comment');
    this.span_total_price_school_curr_currency = dojoWrapper.getById('total_price_school_curr_currency');
    
    this.span_exchange_rate = dojoWrapper.getById('exchange_rate');
    this.row_exchange_rate = dojoWrapper.getById('exchange_rate_row');
    
    this.price_table = dojoWrapper.getById('id_price_calculator_price_table');
    this.buttons_div = dojoWrapper.getById('id_price_calculator_buttons');

	/**
	 *	Waiting dialog widget
	 *      Used for displaying a white overlay when the form is sent
	 */
	this.waiting_widget = dojoWrapper.getById('id_waiting_div');
    
    /**
     * Step_num: defines the logic order of the select boxes
     */
    this.country_select_box.step_num = 1;
    this.city_select_box.step_num = 2;
    this.school_select_box.step_num = 3;
    this.course_select_box.step_num = 4;
    this.accommodation_form_select_box.step_num = 5;
    this.transfer_select_box.step_num = 6;
    this.course_season_select_box.step_num = 7;
    this.course_weeks_select_box.step_num = 8;
    this.accommodation_weeks_select_box.step_num = 9;
    this.locale_currency_select_box.step_num = 10;
    
    /**
     *   Variable: select_boxes
     *       All select boxes in the form, the order is important!
     *       Is used for marking the active select box depending
     *       on the current step
     */
    this.select_boxes = [ 
        '',
        this.country_select_box, 
        this.city_select_box, 
        this.school_select_box, 
        this.course_select_box, 
        this.accommodation_form_select_box,
        this.transfer_select_box,
        this.course_season_select_box,
        this.course_weeks_select_box,
        this.accommodation_weeks_select_box,
        this.locale_currency_select_box
        ];
    
    /* 
        Variable: current_step
            the currently active step 
    */
    this.current_step = 1;

    /**
     *   Corresponding set functions:
     *   Used for setting selected index of the select box artificially;
     *
     *   This function will be invoked:
     *       base_object [ function_str ] ( select box value )
     */
    this.city_select_box.set_function = { base_object: this, function_str: 'set_city' };
    this.school_select_box.set_function = { base_object: this, function_str: 'set_school' };
    this.course_select_box.set_function = { base_object: this,  function_str: 'set_course' };
    this.accommodation_form_select_box.set_function = { base_object: this, function_str: 'set_accommodation_form' };
    this.course_weeks_select_box.set_function = { base_object: this, function_str: 'set_course_weeks' };
    this.accommodation_weeks_select_box.set_function = { base_object: this, function_str: 'set_accommodation_weeks' };

    /**  
     *   Variable: today
     *       Today's date:   
     */
    this.today = today;

    /**  
     *   Variable: void_accommodation_form
     *       Option 'No accommodation form required' is inserted
     *       as first option into each select box
     */
    this.void_accommodation_form = {
        id: no_accommodation_required_value,
        name: no_accommodation_required_text
    };

    /**
     *   Variable: cached_responses
     *       Hash array, as index serves the request string
     */
    this.cached_responses = [];
    
    
    /**
     *   Ajax Request URL
     */
    this.url_fetch_obj = url_fetch_obj;
    
    /**
     *   Variable: properties
     *       Are set to null if the element is disabled
     */
    this.country_select_box.properties = ['country'];
    this.city_select_box.properties = ['city', 'school_set'];
    this.school_select_box.properties = ['school', 'course_set', 'accommodation_form_set', 'school_transfer_set', 'school_inscription_fee_set'];
    
    this.course_select_box.properties = ['course'];
    this.accommodation_form_select_box.properties = ['accommodation_form'];
    this.transfer_select_box.properties = ['transfer'];
    this.course_season_select_box.properties  = ['course_season', 'price_periods'];
    this.course_weeks_select_box.properties = ['course_weeks'];
    this.accommodation_weeks_select_box.properties = ['accommodation_weeks'];
    
    this.span_course_inscription_fee.properties = ['current_course_inscription_fee'];
    this.span_course_price.properties = ['current_course_price'];
    this.span_accommodation_price.properties = ['current_accommodation_price'];
    this.span_accommodation_inscription_fee.properties = ['current_accommodation_inscription_fee'];
    this.span_transfer.properties = ['current_transfer_cost'];
    this.span_total_price.properties = ['total_price'];
    
    /**
     * Variable: price_fields
     *       These fields remain hidden/disabled if not
     *       all select boxes have an option selected
     */
    this.price_fields = [ 
        this.span_course_inscription_fee, 
        this.span_course_inscription_fee_comment,
        
        this.span_course_price, 
        this.span_course_price_currency,
        
        this.span_accommodation_inscription_fee, 
        this.span_accommodation_inscription_fee_comment,
        
        this.span_accommodation_price, 
        this.span_accommodation_price_currency,
        
        this.span_transfer, 
        this.span_transfer_currency,
        
        this.span_school_material_fee_amount,
        this.span_school_material_fee_currency,
        
        this.span_total_price, 
        this.span_total_price_currency,
        /* this.span_total_price_comment, */
        
        this.span_total_price_school_curr, 
        this.span_total_price_school_curr_currency,
        /* this.span_total_price_school_curr_comment ,*/
       
        this.exchange_rate_row,

        this.add_to_cart_button, 
        this.book_button
    ];
    
    /**
     *   Select Box Children Elements:
     *       User interface elements that are directly related,
     *       and should be disabled when a new item is selected
     *       
     *       e.g. when a country is selected from the country select box
     *       the city select box is disabled until the related cities are filled in
     */        
    this.country_select_box.children_elements = [this.city_select_box];
    this.city_select_box.children_elements    = [this.school_select_box];
    this.school_select_box.children_elements  = [this.course_select_box];
    
    this.course_select_box.children_elements  = [this.accommodation_form_select_box];
    this.accommodation_form_select_box.children_elements = [this.transfer_select_box, this.course_season_select_box];
    this.transfer_select_box.children_elements = [];
    
    this.course_season_select_box.children_elements = [this.course_weeks_select_box, this.accommodation_weeks_select_box];
    this.course_weeks_select_box.children_elements = [this.accommodation_weeks_select_box];
    this.accommodation_weeks_select_box.children_elements = [];
    
    this.locale_currency_select_box.children_elements = [];
    
    /*
        Function: get_course_prices
            Searches the course prices and returns a course price with 
            from_date <= a_from_date and to_date > a_from_date.
        
        Returns:
            Float, course price
            Null, if no date is found
    */
    this.get_course_prices = function ( a_from_date )
    {                 
        var a_course_price_list = find_period_with_date( a_from_date, this.course_price_set  );
        return a_course_price_list;            
    };

    /*
        Function: get_accommodation_prices
            Searches all the accommodation
            prices and returns a accommodation price with
            from_date before or equal to a_from_date and
            to_date after a_from_date.
            
            If there is no such date, it returns null.
            
        Returns:
            Array, accommodation prices
            Null, if no date is found
    */
    this.get_accommodation_prices = function ( a_from_date )
    {
        var an_accommodation_price_list = find_period_with_date ( a_from_date, this.accommodation_price_set );         
        return an_accommodation_price_list;            
    };

    /*
        Function: get_week_price
            Searches a_price_list
            and returns the attribute of a_price_list
            for the corresponding week.  
    */
    this.get_week_price = function ( a_price_list, a_weeks )
    {
        var field_prefix = 'week';
        return a_price_list[ field_prefix + a_weeks ];
    };
    
    /*
        Function: get_max_weeks
            Searches all the properties of a_price_list
            and determines the longest week period.
            
            e.g: a_price_list.week24 !== undefined,
            returns 24 (even if a_price_list.week24 == null )
    */
    this.get_max_weeks = function ( a_price_list )
    {
        var field_prefix = 'week';
        var max_weeks = 0;
        var num_weeks = null;
        
        /*
            Go through all the properties:            
        */
        for ( var a_property in a_price_list )
        {                
            /*
                Ignore if it's a function:
            */                
            if ( is_function( a_price_list[a_property] ) )
            {
                continue;
            }
            
            if ( a_property.substr(0, field_prefix.length) === field_prefix )
            {
                num_weeks = a_property.substr(field_prefix.length, a_property.length - field_prefix.length);         
                
                if ( Number(num_weeks) > max_weeks )
                {
                    max_weeks = Number(num_weeks);
                }                                                                
            }
        }
        
        return max_weeks;
    };
          
    /*
        Function: set_active
            change the appearance of the select box to active
    */
    this.set_active = function ( element_id )
    {
        var element = dojoWrapper.getById(element_id);
        element.parentNode.className = 'price_calculator_active_element';
        
        var active_image_id = 'id_price_calculator_' + element.name + '_active_img';
        var inactive_image_id = 'id_price_calculator_' + element.name + '_inactive_img';
        
		var active_image = dojoWrapper.getById(active_image_id);
		if (active_image !== null) {
			active_image.style.display = 'inline';
		}
        var inactive_image = dojoWrapper.getById(inactive_image_id);
		if (inactive_image !== null) {
			inactive_image.style.display = 'none';
		}
    }; 
    
    /*
        Function: set_inactive
            change the appearance of the select box to inactive
    */
    this.set_inactive = function ( element_id )
    {
        var element = dojoWrapper.getById(element_id);
        element.parentNode.className = 'price_calculator_inactive_element';
        
        var active_image_id = 'id_price_calculator_' + element.name + '_active_img';
        var inactive_image_id = 'id_price_calculator_' + element.name + '_inactive_img';
        
		var active_image = dojoWrapper.getById(active_image_id);
		if (active_image !== null) {
			active_image.style.display = 'none';
		}
        var inactive_image = dojoWrapper.getById(inactive_image_id);
		if (inactive_image !== null) {
			inactive_image.style.display = 'inline';
		}
    };
    
    /*
        Function: update_active_step
            update the state of the GUI so that only the select_box is marked active
            which corresponds to the current internal state (step number)
        
        Parameters:
            next_step - Int, the next active step
    */
    this.update_active_step = function (next_step)
    {
        this.current_step = next_step;
		if (this.current_step === null)
		{
			this.current_step = 1;
		}
        //this.current_step = 1;
        
        // check if the country is selected 
        if (this.current_step === this.country_select_box.step_num && this.country)
        {
            this.current_step++;
        }
        
        // check if the city is selected 
        if (this.current_step === this.city_select_box.step_num && this.city)
        {
            this.current_step++;
        }
        
        // check if a school is selected
        if (this.current_step === this.school_select_box.step_num && this.school)
        {
            this.current_step ++;
        }
        
        // check if a course is selected
        if (this.current_step === this.course_select_box.step_num && this.course)
        {
            this.current_step++;
        }	

        // check if an accommodation form is selected
        if (this.current_step === this.accommodation_form_select_box.step_num)
		{
			if (this.accommodation_form)
			{
				this.current_step++;
			}
			else if (this.accommodation_form_set)
			{
				this.fill_accommodation_forms(this.accommodation_form_set);
			}
            
            this.transfer = null;
		}
        
        // check if transfer is selected
        if (this.current_step === this.transfer_select_box.step_num)
        {
            if (this.transfer == null)
            {
                /*
                    Fill transfer
                */
                if (!this.school_transfer_set || this.school_transfer_set.length == 0)
                {
                    this.transfer = false;
                    this.current_step++;
                }
                else if (this.school_transfer_set)
                {
                    this.fill_transfer();
                }
            }
            else
            {
                this.current_step++;
            }
        }
        
        // check if a course season (start) is selected
        if (this.current_step === this.course_season_select_box.step_num)
        {
            if (!this.course_season)
            {
                this.fill_seasons();
            }
            
            if (this.course_season_tmp)
            {
                this.course_season = this.course_season_tmp;
            }
            
            if (this.course_season && this.course_price_set)
            {
                // update the price tables
                this.school_demonstrator.set_course_starting_date(this.course_season);
                this.current_step++;
            }
        }
        
        // check if the course weeks is selected
        if (this.current_step === this.course_weeks_select_box.step_num)
        {
            if (!this.course_weeks)
            {
            	this.fill_course_weeks(this.course_season);
            }
            else 
            {
                // TODO: re-enable yalea sequence (without accommodation weeks select box)
                /*
                if (a_money_exchange.locale_currency === null)
                {
                    a_money_exchange.fill_currency_select_box();
                }
                */
    			
                this.current_step++;
            }
        }
        
        // check if the accommodation weeks is selected
        if (this.current_step == this.accommodation_weeks_select_box.step_num)
        {
            if (!this.accommodation_weeks)
            {
               if (this.accommodation_form !== this.void_accommodation_form)
               {
            	   this.fill_accommodation_weeks(this.course_season);
               }
               else
               {
                   this.accommodation_weeks = 0;
                   this.current_step++;
               }
            }
            else
            {
                this.current_step++;
            }
        }
        
        // check if a locale currency is selected
        if (this.current_step === this.locale_currency_select_box.step_num)
        {
            if (!a_money_exchange.locale_currency)
            {
                if (a_money_exchange.locale_currency === null)
                {
                    a_money_exchange.fill_currency_select_box();
                }
            }
            else
            {
                this.calculate_prices(this);              
                
                // show buttons
                this.buttons_div.style.display = '';
                
                this.current_step++;
            }
        }
        if (!a_money_exchange.locale_currency)
        {
            // Hide buttons
            this.buttons_div.style.display = 'none';
        }
        
        // update all select boxes to reflect the current state        
        for (var i = 1; i < this.select_boxes.length; i++)
        {
            if (i === this.current_step)
            {
                this.enable_obj(this.select_boxes[i]);
                this.set_active(this.select_boxes[i]);
            }
            else
            {
                this.set_inactive(this.select_boxes[i]);
            }
        }
    };
    
    /*
        Function: set_country
            sets the country, erases select boxes 
            and fills them when the data is received.
    */
    this.set_country = function ( a_country_id )
    {
        /*
            Set the select box to point to the a_country_id:            
        */
        this.set_select_box ( this.country_select_box, a_country_id );
        this.disable_obj_children ( this.country_select_box );
        this.clear_properties ( this.country_select_box );


        if ( a_country_id )            
        {                        
            /*
                Set country property of this instance:
            */
            this.country = this.find_obj_with_id( a_country_id, this.country_set );
			
			
            this.send_request( this.city_set_request(a_country_id), this, 'fill_cities' );
			
			

        }
        // change the appearance of the select_box
        this.update_active_step(this.country_select_box.step_num);
		
    }; 

    /*
        Function: set_city
            Sets the city, erases the affected select boxes and fills them up when the data is received.  
    */
    this.set_city = function ( a_city_id )
    {
        /*
            Set the select box to point to the a_city_id:            
        */                   
        this.set_select_box ( this.city_select_box, a_city_id );
        this.disable_obj_children ( this.city_select_box );     
        this.clear_properties ( this.city_select_box );     
        
        if ( a_city_id )
        {
            /*
                Set city property of this instance:
            */ 
		   
            this.city = this.find_obj_with_id ( a_city_id, this.city_set ); 
            this.send_request( this.school_set_request(a_city_id), this, 'fill_schools' );
        }
        this.update_active_step(this.city_select_box.step_num);
		
    };
    
    /*
        Function: set_school
            Sets the school variable, fetches school information. 
            
            Fills accommodation forms and courses select boxes.     
    */
    this.set_school = function (school_id)
    {
        /*
            Set the select box to point to the a_school_id:            
        */
        this.set_select_box(this.school_select_box, school_id);
        this.disable_obj_children(this.school_select_box);
        this.clear_properties(this.school_select_box);

        if (school_id)
        {           
            /*
                Reset previously used data
            */    
            this.school                      = null;
            this.accommodation_form_set      = null;
            this.course_set                  = null;
            
            this.accommodation_price_set     = null;
            this.course_price_set            = null;

            this.school_transfer_set = null;
            this.school_inscription_fee_set = null;
            
            this.school_material_fee_set     = null;
            
            /*
                Send request for the current school:
            */
            this.send_school_request(school_id);
            
            /*
                Show the school in the school demonstrator:                    
            */
            this.school_demonstrator.show_school(school_id); 
        }
        
        this.update_active_step(this.school_select_box.step_num);
		
    };
    
    /*
        Function: set_course
            Sets the course, sends a request for price lists
    */
    this.set_course = function ( a_course_id )
    {       
        /*
            Set the select box to point to the a_course_id:            
        */
        this.set_select_box(this.course_select_box, a_course_id);
        this.disable_obj_children(this.course_select_box);
        this.clear_properties(this.course_select_box);
                    
        if ( a_course_id )
        {
            /*
                Set the course property of the instance:
            */
            this.course = this.find_obj_with_id(a_course_id, this.course_set);
			
            /*
                Send request for course prices:                
            */
            this.course_price_set = null;
            var request = this.course_price_request(a_course_id);
            this.send_request(request, this, 'save_course_package');
        }
        
        // do not update now, but just when the data is received
    };
    
    /**
     * Saves a course package and updates the user interface
     * @param {Object} a_package
     */
    this.save_course_package = function(a_package)
    {
        this.save_package(a_package);
        this.update_active_step(this.course_select_box.step_num);
    };
    
    /*
        Function: set_accommodation_form
            Sets the accommodation form, sends a request for price lists
    */
    this.set_accommodation_form = function ( an_accommodation_form_id )
    {
		/*
            Set the select box to point to the an_accommodation_form_id:            
        */
        this.set_select_box(this.accommodation_form_select_box, an_accommodation_form_id);
        this.disable_obj_children(this.accommodation_form_select_box);
        this.clear_properties(this.accommodation_form_select_box);
        
        if (an_accommodation_form_id)
        {
            if (an_accommodation_form_id === this.void_accommodation_form.id)
            {
                /*
                    No accommodation form required.
                */
                this.accommodation_form = this.void_accommodation_form;
                this.accommodation_price_set = null;
            }
    		else
    		{
    	        /*
    	            Accommodation form required.
    	        */
    	        this.accommodation_form = this.find_obj_with_id(an_accommodation_form_id, this.accommodation_form_set);
    	        
    			/*
    	            Send request for accommodation prices:                
    	        */ 
    	        this.accommodation_price_set = null;
    			var request = this.accommodation_price_request(an_accommodation_form_id);
    	        this.send_request(request, this, 'save_accommodation_package');
            }
        }
		
        this.update_active_step(this.accommodation_form_select_box.step_num);
    };
    
    /**
     * Saves an accommodation package and updates the user interface
     * @param {Object} a_package
     */
    this.save_accommodation_package = function(a_package)
    {
        this.save_package(a_package);
        this.update_active_step(this.accommodation_form_select_box.step_num);
    };
    
    /*
        Function: set_transfer
            Sets the transfer property of the instance and sets 
            the transfer select box option to the option of the switch.
            This function is called by the html element and by internal code.
    */
    this.set_transfer = function ( transfer_id )
    {
        this.set_select_box( this.transfer_select_box, transfer_id );
        this.disable_obj_children( this.transfer_select_box );
        this.clear_properties( this.transfer_select_box );
        
        this.transfer_price_set = null;
        
        this.enable_only_direct_obj_children(this.transfer_select_box);
        
        if (transfer_id > 0)
        {
            var a_transfer = this.find_obj_with_id(transfer_id, this.school_transfer_set);
            this.transfer = { id: a_transfer.id, name: gettext('Transfer')+': '+a_transfer.name };
            
            // Send a request for transfer prices 
            var request = this.transfer_price_request(transfer_id);
            this.send_request(request, this, 'save_transfer_package');
        }
        else
        {
            this.transfer = { id: 0, name: gettext('Ohne Transfer') };
            this.current_step++;
        }
    };
    
    /**
     * Saves an transfer package and updates the user interface
     * @param {Object} a_package
     */
    this.save_transfer_package = function(a_package)
    {
        this.save_package(a_package);
        this.update_active_step(this.transfer_select_box.step_num);
    };

    /*
        Function: set_course_season
            sets course_season property of 
            the instance and enables calculate price button.
            This function is called by the 'select' element
    */
    this.set_course_season = function ( a_from_date )
    {
        // Set the select box to point to the a_from_date
        this.set_select_box(this.course_season_select_box, a_from_date);
        
        // set the select box of the school demonstrator too
        var pricePeriodsSelectBox = dojoWrapper.getById('id_school_demonstrator_select_course_season');
        if (pricePeriodsSelectBox !== null)
        {
            this.set_select_box(pricePeriodsSelectBox, a_from_date);
        }
            
        this.disable_obj_children(this.course_season_select_box);
        this.clear_properties(this.course_season_select_box);
        
        if (a_from_date)
        {
            this.course_season = a_from_date;
        }
        else
        {
            this.course_season = null;
        }
        
        this.update_active_step(this.course_season_select_box.step_num);
    };
    
    /*
        Function: set_course_weeks
           sets course weeks and 
           enables calculate button as well as transfer checkbox.       
           
           a_course_weeks is just a number of the weeks the user would like to book. 
    */
    this.set_course_weeks = function ( a_course_weeks )
    {
        this.set_select_box( this.course_weeks_select_box, a_course_weeks );
        this.disable_obj_children( this.course_weeks_select_box );
        this.clear_properties( this.course_weeks_select_box );
        
        if (a_course_weeks)
        {
            this.course_weeks = Number(a_course_weeks);
        }
        else
        {
            this.course_weeks = null;
        }
        
        this.update_active_step(this.course_weeks_select_box.step_num);         
    };
    
    /*
        Function: set_accommodation_weeks
            sets accommodation weeks, enables calculation
            
        Parameters:
            accommodation_weeks - number of weeks
    */
    this.set_accommodation_weeks = function(accommodation_weeks)
    {
        this.set_select_box(this.accommodation_weeks_select_box, accommodation_weeks);
        this.disable_obj_children(this.accommodation_weeks_select_box);
        this.clear_properties(this.accommodation_weeks_select_box);
        
        if (accommodation_weeks)
        {
            this.accommodation_weeks = Number(accommodation_weeks);
        }
        else 
        {
            this.accommodation_weeks = null;
        }
        
        this.update_active_step(this.accommodation_weeks_select_box.step_num);     
    };
    
    /*
        Function: set_locale_currency
            Updates the current step and refreshes the GUI
    */
    this.set_locale_currency = function ( a_locale_currency )
    {
        if (a_locale_currency !== "")
        {
            a_money_exchange.set_locale_currency_with_abb( a_locale_currency );
            this.update_active_step(this.locale_currency_select_box.step_num);
            
            /*
                Make the prices update when the currency changes
                (publisher/subscriber)
            */
            a_money_exchange.sign_off_object_for_update(this, this.calculate_prices);     
            a_money_exchange.sign_up_object_for_update(this, this.calculate_prices);
            
            /*
                    Update price cells content
                    according to locale currency:            
            */
            a_money_exchange.update_signed_up_objects();
        }
    };
    
    /*
        Function: calculate_prices
            Takes care of calculating all the prices and displaying them to the user.                            
            
            If there is data missing, it will hide the prices and disable buttons for the booking.
    */
    this.calculate_prices = function ( a_self )
    {
        if ( a_self.school &&
             a_self.course &&
             a_self.accommodation_form &&
             a_self.transfer !== null &&
             a_self.course_weeks &&
             a_self.course_season )
        {   
            var school_currency_abb = a_money_exchange.find_currency_with_id( a_self.school.currency ).abbreviation;
            var school_currency_str = school_currency_abb.toUpperCase();
            
            /*    
                Course price:    
            */
            var course_price = 0;
            var course_price_list = a_self.get_course_prices(a_self.course_season);
            course_price  = a_self.get_week_price(course_price_list, a_self.course_weeks);
            if (course_price)
            {
                // Course inscription fee (if available)
                var course_inscription_fee = 0;
                var an_inscription_fee = find_period_with_date(a_self.course_season, a_self.school_inscription_fee_set);
                
                if (an_inscription_fee)
                {
                    course_inscription_fee = an_inscription_fee.fee;
                    //course_price += course_inscription_fee;
                    
					
					// New for yalea:
                    //var inscription_fee_str = a_money_exchange.repr_amount_in(school_currency_abb, course_inscription_fee);
                    var inscription_fee_str = a_money_exchange.amount_to_str(course_inscription_fee);
					
					// New for yalea:
				 	a_self.span_course_inscription_fee_currency.innerHTML = school_currency_str;
                	a_self.span_course_inscription_fee_currency.style.display = '';
					
					// New for yalea:
					//a_self.span_course_inscription_fee.innerHTML = '&nbsp;('+gettext('inkl.')+' '+inscription_fee_str+' '+gettext('Einschreibung')+')';
					a_self.span_course_inscription_fee.innerHTML = inscription_fee_str;                    
					
					a_self.span_course_inscription_fee.style.display = '';
                }
                else
                {
                    a_self.span_course_inscription_fee.style.display = 'none';   
                }
                
                // Course exam fee (if available)
                var course_exam_fee = 0;
                var an_exam_fee = course_price_list.exam_fee;
                if (an_exam_fee && an_exam_fee > 0)
                {
                    course_exam_fee = an_exam_fee;
                    var exam_fee_str = a_money_exchange.amount_to_str(course_exam_fee);
                    
                    a_self.span_course_exam_fee_amount.innerHTML = exam_fee_str;
                    a_self.span_course_exam_fee_currency.innerHTML = school_currency_str;
                    a_self.course_exam_fee_row.style.display = '';
                }
                else
                {
                    a_self.course_exam_fee_row.style.display = 'none';
                }
                     
                var a_course_price_str = a_money_exchange.amount_to_str(course_price);
                a_self.span_course_price_currency.innerHTML = school_currency_str;
                a_self.span_course_price_currency.style.display = '';
                a_self.span_course_price.innerHTML = a_course_price_str;                         
                a_self.span_course_price.style.display = '';
            }
            
            /*
             *   Material fee
             */
            var school_material_fee = 0;
            var material_fee_obj = find_period_with_date(a_self.course_season, a_self.school_material_fee_set);
            if (material_fee_obj)
            {
                school_material_fee = a_self.get_week_price(material_fee_obj, a_self.course_weeks);
                var material_fee_str = a_money_exchange.amount_to_str(school_material_fee);
                
                a_self.span_school_material_fee_amount.innerHTML = material_fee_str;
                a_self.span_school_material_fee_currency.innerHTML = school_currency_str;
                
				// New for yalea
                a_self.school_material_fee_row.style.display = 'none';
            }
            else
            {
                a_self.school_material_fee_row.style.display = 'none';
            }
            
            /*    
                Accommodation price:    
            */
            var accommodation_price = 0;
            if (a_self.accommodation_form !== a_self.void_accommodation_form)            
            {
                var accommodation_price_obj = a_self.get_accommodation_prices(a_self.course_season);
                var accommodation_price = a_self.get_week_price(accommodation_price_obj, a_self.accommodation_weeks);
                 
                /*
                    Check if the value is available - we want only to display 
                    prices only when every piece of information is available.
                */                        
                if (accommodation_price !== null )
                {
                    /*
                     * Add accommodation inscription fee (if available)
                     */
                    if (accommodation_price_obj.inscription_fee && a_self.span_accommodation_inscription_fee)
                    {
                        // add the inscription fee to the price
                        var accommodation_inscription_fee = accommodation_price_obj.inscription_fee;
                        accommodation_price = accommodation_price + accommodation_inscription_fee;
                        
                        var locale_fee =  a_money_exchange.repr_amount_in(school_currency_abb, accommodation_inscription_fee);
                        var fee_str = '<br />(' + gettext('inkl.') + ' ' + locale_fee + ' ' + gettext('Einschreibung') + ')';
                        a_self.span_accommodation_inscription_fee.innerHTML = fee_str;
                        a_self.span_accommodation_inscription_fee.style.display = '';
                    }
                    else {
                        a_self.span_accommodation_inscription_fee.style.display = 'none';
                    }                                                         
                    
                    var an_accommodation_price_str = a_money_exchange.amount_to_str(accommodation_price);
                    
                    a_self.span_accommodation_price_currency.innerHTML = school_currency_str;
                    a_self.span_accommodation_price_currency.style.display = '';
                    a_self.span_accommodation_price.innerHTML = an_accommodation_price_str;
                    a_self.span_accommodation_price.style.display = '';
                }
                
                a_self.accommodation_price_row.style.display = '';
            }
            else
            {
                a_self.accommodation_price_row.style.display = 'none';
            }
            
            /* 
               Transfer cost:    
            */
            var transfer_cost = 0;
            if (a_self.transfer && a_self.transfer.id > 0)
            {
                var transfer_price_obj = find_period_with_date(a_self.course_season, a_self.school_transfer_price_set);
                if (transfer_price_obj !== null)
                {
                    transfer_cost = transfer_price_obj.cost;
                    var transfer_cost_str = a_money_exchange.amount_to_str(transfer_cost);
                                                        
                    a_self.span_transfer_currency.innerHTML = school_currency_str;
                    a_self.span_transfer_currency.style.display = '';
                    a_self.span_transfer.innerHTML = transfer_cost_str;
                    a_self.span_transfer.style.display = '';
                    
                    a_self.transfer_cost_row.style.display = '';
                }   
            } 
            else
            {
                a_self.transfer_cost_row.style.display = 'none';
            }
            
            /* 
                Total price:    
            */
            a_self.total_price = course_price + 
                                 accommodation_price +
                                 school_material_fee +
                                 course_exam_fee +
								 course_inscription_fee + 
                                 transfer_cost;
                
            /*
                Total price in school currency:
            */
            if (a_self.total_price)
            {
                var a_total_price_in_school_curr_str = a_money_exchange.amount_to_str(a_self.total_price);
                
                a_self.span_total_price_school_curr_currency.innerHTML = school_currency_str;
                a_self.span_total_price_school_curr_currency.style.display = '';
                
                a_self.span_total_price_school_curr.innerHTML = a_total_price_in_school_curr_str;
                a_self.span_total_price_school_curr.style.display = '';     
            }                  
            else
            {
                a_self.span_total_price_school_curr_currency.innerHTML = '';
            }
            
            /*
             *   Show exchange rate
             */
            if (a_money_exchange.locale_currency && 
                school_currency_abb !== a_money_exchange.locale_currency && 
                a_self.row_exchange_rate != null)
            {
                var locale_abb = a_money_exchange.locale_currency.abbreviation;
                var locale_str = locale_abb.toUpperCase();
                var rate = a_money_exchange.to_locale_currency(school_currency_abb, 1.0);
				
				var indexOfPoint = rate.toString().indexOf ( '.' );
				var rateStringLength = rate.toString ().length;
				
				
				if ( indexOfPoint < 0 )
				{
					// rate is an integer, have to add the decimal places
					rate = rate + '.00';
					indexOfPoint = rate.toString().indexOf ( '.' );
					rateStringLength = rate.toString ().length;
				}
				
			
				
				// The point must be at third position from the end, otherwise, we need to add zeros
				if ( indexOfPoint != ( rateStringLength - 3 ) )
				{
					rate = rate + '0';
				}
                a_self.span_exchange_rate.innerHTML = '1 '+school_currency_str+' = '+rate+' '+locale_str;
                
                a_self.row_exchange_rate.style.display = '';
            }
            else {
                a_self.row_exchange_rate.style.display = 'none';
            }
            
            /*
                Total price in local currency
            */                    
            if (a_self.total_price && a_money_exchange.locale_currency)
            {
                var locale_currency_abb = a_money_exchange.locale_currency.abbreviation;
                
                var a_total_price_locale = a_money_exchange.to_locale_currency(school_currency_abb, a_self.total_price);
                var a_total_price_str = a_money_exchange.amount_to_str(a_total_price_locale);
                
                a_self.span_total_price_currency.innerHTML = locale_currency_abb.toUpperCase();
                a_self.span_total_price_currency.style.display = '';
                
                a_self.span_total_price.innerHTML = a_total_price_str;
                a_self.span_total_price.style.display = '';
                
                a_self.span_total_price_comment.style.display = '';
            }
            else
            {
                 a_self.span_total_price_currency.innerHTML = '';
                 a_self.span_total_price.innerHTML = '';
            }
            
            if (this.price_table)
            {
                this.price_table.style.display = '';
            }
        }         
        else
        {
            /*
                There is some data missing,
                disable all objects in price_cells_and_buttons:
            */
            for ( var i = 0; i < a_self.price_fields.length; i ++ )
            {
                a_self.disable_obj( a_self.price_fields[i] );
            }
            
            if (this.price_table)
            {
                this.price_table.style.display = 'none';
            }
        }       
    };
    
    this.saveWare = function()
    {
        var ware = {
            'country_id': this.country.id,
            'country_name': this.country.name,
            'city_id': this.city.id,
            'city_name': this.city.name,
            'school_id': this.school.id,
            'school_name': this.school.name,
            'course_id': this.course.id,
            'course_name': this.course.name,
            'accommodation_form_id': this.accommodation_form.id,
            'accommodation_form_name': this.accommodation_form.name,
            'course_weeks': this.course_weeks,
            'accommodation_weeks': this.accommodation_weeks,
            'transfer_id': this.transfer.id,
            'transfer_name': this.transfer.name,
            'total_price': this.total_price,
            'school_currency_abb': a_money_exchange.find_currency_with_id(this.school.currency).abbreviation.toUpperCase(),
            'locale_currency_abb' : a_money_exchange.locale_currency.abbreviation.toUpperCase()
        };
        return ware;
    };
    
    /*
        Function: save_to_cart
            Propagates booking information to cart and makes proceed to booking button disapear ( it will apear in the cart ).
    */
    this.save_to_cart = function()
    {

        var ware = this.saveWare();
        a_cart.add_ware(ware);
        a_cart.save();
        
        /*
            Make book button disappear:
        */                                    
        //this.book_button.setDisabled ( true );
        //this.disable_obj(this.book_button);
    };
    
    /*
     *
     */
    this.submit = function(ware_pkg, locale_currency_abb)
    {
        attach_hidden_field_to_form(this.form, 'package', ware_pkg );
        attach_hidden_field_to_form(this.form, 'locale_currency_abb', locale_currency_abb);
    	
    	if (this.waiting_widget)
        {
			dojoWrapper.setStyle ( this.waiting_widget, "display", "block" );
        }
		
        this.form.submit();
    };

    /*
        Function: show_the_booking
            Redirects the user to the booking page
    */
    this.show_the_booking = function()
    {
        var a_ware = this.saveWare();
        var ware_pkg = dojoWrapper.serializeToJson([a_ware]);
        var locale_currency_abb = a_money_exchange.locale_currency.abbreviation;
        
        this.submit(ware_pkg, locale_currency_abb);
    };

    /*
        Function: save_school_sets
            Manages saving the received school information.
            
            It saves the package and then checks if all important packages are received:
            
            - school, course_set, 
            - accommodation_form_set
            - school_inscription_fee_set
            - school_transfer_set
            
            We should wait until we have gathered all of them.
    */
    this.save_school_sets = function ( a_package )
    {
        /*
            We only want to take some action if there is really a package,
            otherwise we do as if nothing happened:            
        */
        	                       
        if (a_package)
        {
            /*
                Save it:                
            */
            this.save_package(a_package);                                                
            
            if ( this.school && 
                 this.course_set && 
                 this.accommodation_form_set &&
                 this.school_transfer_set &&
                 this.school_inscription_fee_set &&
                 this.school_material_fee_set )
            {
                /*
                    We received all the important packages!             
                */       
                
                /*
                    Save some school info
                    needed because school assistant skips country/city selection step
                */
                if (!this.country)
                {
                    this.country = { id: this.school.country_id, name: this.school.country_name };
                }
                if (!this.city)
                {
                    this.city = { id: this.school.city_id, name: this.school.city_name };
                }
                
	        	/*
                    Fill courses select box:
                */
                this.fill_courses(this.course_set);

                /*
                    Add void accommodation form to the accommodation form set:
                */		
                this.accommodation_form_set.unshift(this.void_accommodation_form);                       
            }
            /*
             * Do nothing until all data was received
            */
        }       
    };

    /**
     * Function: save_package
     *       The entry defined by important_part of the package will be saved in this instance.
     *       
     *       if property is not null or undefined, an error will be raised.
     *
     * @param {Object} a_package
     */
    this.save_package = function ( a_package )
    {  
        if ( !a_package )
        {
            show_errors( ['Price calculator: There is no package specified.'] );
        }
        else if ( !a_package.important_part || a_package.important_part === '' )
        {
            //alert( typeof( a_package ) );
            show_errors( [ 'Price calculator: Important part of the package is not specified.' ] );
        } 
        else
        {
            var important_property = a_package.important_part;
            this[ important_property ] = a_package[ important_property ];
        }
    };
    
    /*
        Function: set_select_box
            Set the active item of a select box
        
        Parameters:
            a_select_box - Select box element
            a_value - String, option to select
    */
    this.set_select_box = function ( a_select_box, a_value )
    {
        if ( a_select_box != a_value )
        {
            for ( var i = 0; i < a_select_box.options.length; i ++ )
            {
                // intentionally allow comparison between int and string!
                if ( a_value == a_select_box.options[i].value )
                {
                    a_select_box.selectedIndex = i;
                    break;
                }
            }
        }
    };                                              
    
    /*
        -------------------------
        User interface functions:
        -------------------------
    */       
    
    /*
        Function: hide_price_period_span
            Hides the price period select box and arranges the layout.
    */
    this.hide_price_period_span = function ()
    {
        /* change the src for "course weeks" */
        var course_weeks_active_image = dojoWrapper.getById('id_price_calculator_' + this.course_weeks_select_box.name + '_active_img');
        var course_weeks_inactive_image = dojoWrapper.getById('id_price_calculator_' + this.course_weeks_select_box.name + '_inactive_img');
        var locale_currency_active_image = dojoWrapper.getById('id_price_calculator_' + this.locale_currency_select_box.name + '_active_img');
        var locale_currency_inactive_image = dojoWrapper.getById('id_price_calculator_' + this.locale_currency_select_box.name + '_inactive_img');
        
        var num4_active_image = dojoWrapper.getById('id_price_calculator_num_4_active_img');
        var num4_inactive_image = dojoWrapper.getById('id_price_calculator_num_4_inactive_img');
        var num5_active_image = dojoWrapper.getById('id_price_calculator_num_5_active_img');
        var num5_inactive_image = dojoWrapper.getById('id_price_calculator_num_5_inactive_img');
        
        /* change the path to number 4 for "course weeks" */
		if (course_weeks_active_image && course_weeks_inactive_image)
		{
	        course_weeks_active_image.src = num4_active_image.src;
    	    course_weeks_inactive_image.src = num4_inactive_image.src;
		}
		
        /* change the path to number 5 for "local currency" */
		if (locale_currency_active_image && locale_currency_inactive_image)
		{
	        locale_currency_active_image.src = num5_active_image.src;
    	    locale_currency_inactive_image.src = num5_inactive_image.src;
		}
        
        /*
            Hide price period span:
        */
        this.disable_obj(this.price_period_span);
        this.disable_obj(this.price_period_number_span);                                                 
    };
    
    /*
        Function: show_price_period_span
            Shows the price period select box and arranges the layout.
    */
    this.show_price_period_span = function ()
    {
        /* change the src for "course weeks" */
        var course_weeks_active_image = dojoWrapper.getById('id_price_calculator_' + this.course_weeks_select_box.name + '_active_img');
        var course_weeks_inactive_image = dojoWrapper.getById('id_price_calculator_' + this.course_weeks_select_box.name + '_inactive_img');
        var locale_currency_active_image = dojoWrapper.getById('id_price_calculator_' + this.locale_currency_select_box.name + '_active_img');
        var locale_currency_inactive_image = dojoWrapper.getById('id_price_calculator_' + this.locale_currency_select_box.name + '_inactive_img');
        
        var num5_active_image = dojoWrapper.getById('id_price_calculator_num_5_active_img');
        var num5_inactive_image = dojoWrapper.getById('id_price_calculator_num_5_inactive_img');
        var num6_active_image = dojoWrapper.getById('id_price_calculator_num_6_active_img');
        var num6_inactive_image = dojoWrapper.getById('id_price_calculator_num_6_inactive_img');
        
        /* change the path to number 5 for "course weeks" */
		if (course_weeks_active_image && course_weeks_inactive_image)
		{
        	course_weeks_active_image.src = num5_active_image.src;
        	course_weeks_inactive_image.src = num5_inactive_image.src;
		}
		
        /* change the path to number 6 for "local currency" */
		if (locale_currency_active_image && locale_currency_inactive_image)
		{
        	locale_currency_active_image.src = num6_active_image.src;
        	locale_currency_inactive_image.src = num6_inactive_image.src;
		}

        /*
            Show price period span:
        */
        this.enable_obj(this.price_period_span);    
        this.enable_obj(this.price_period_number_span);                                      
    };
    
    /*
        Function: fill_countries
            Fills the select box with countries received from the server.            
            
            Moreover, it sets country_set variable of this instance.
    */
    this.fill_countries = function ( a_package )
    {
        this.country_set = a_package.country_set;
        var please_choose_a_country_option = new Option(gettext('Bitte wähle ein Land:'), '');
        
        this.fill_select_box(a_package.country_set,
                             this.country_select_box,
                             'id',
                             'name',
                             [please_choose_a_country_option]);
    };

    /*
        Function: fill_cities
            fills the select box with cities
            received from the server.            
            
            Sets city_set of the current istance.
    */
    this.fill_cities = function ( a_package )
    {  
	
        this.city_set = a_package.city_set;
		
        var please_choose_a_city_option = new Option( gettext ( 'Bitte wähle eine Stadt:' ), '');                
        this.fill_select_box ( this.city_set, this.city_select_box, 
                                       'id', 'name',
                                       [ please_choose_a_city_option ],
                                       true /* set_if_only_one_option */
                                     );  
    };
	
    
    /*
        Function: fill_schools
            fills the select box with schools received from the server. 
    */
    this.fill_schools = function ( a_package )
    {                                          
        this.school_set = a_package.school_set;
        var please_choose_a_school_option = new Option( gettext ( 'Bitte wähle eine Schule:' ), '' );                
        
        this.fill_select_box ( a_package.school_set, 
                               this.school_select_box, 
                               'id', 'name',
                               [ please_choose_a_school_option ],
                               true /* set_if_only_one_option */ );
                               
        this.update_active_step(this.school_select_box.step_num);
    };
    
    /*
        Function: fill_courses
            fills the select box with courses
            received from the server.   
    */
    this.fill_courses = function(a_course_set)
    {
		
		course_dict = a_course_set [ a_course_set.length - 1 ];
        // clear options
        this.course_select_box.innerHTML = '';
        
        // insert first option
        var option = new Option(gettext('Bitte wähle einen Kurs:'), '');           
        add_option_to_select_box(this.course_select_box, option);             
        
        // insert entries
        // Make option groups for entries which have the same group name
        // 'id', 'name', 'type'
        var option_group;
        var prev_group_str = "";
		
        for (var j = a_course_set.length - 2; j >= 0; j--)
        {
			
            var group_str = course_dict [ a_course_set[j].type ];
            if (group_str != prev_group_str) {
                option_group = document.createElement('optgroup');
                option_group.setAttribute('label', group_str);
                this.course_select_box.appendChild(option_group);
                prev_group_str = group_str;
            }
            
            var element_str = a_course_set[j].name;
            option = document.createElement("option");
            option.appendChild(document.createTextNode(element_str));
            option.value = a_course_set[j].id;
            option_group.appendChild(option);
        }
        
        // select if single option
        if (a_course_set.length === 1)
        {
            this.course_select_box.selectedIndex = 1;
            a_price_calculator.set_course(this.course_select_box.value);
        }
        
        // disable if zero courses available
        if (a_course_set.length === 0) {
            this.course_select_box.innerHTML = '';
            option = new Option( gettext('Keine Kurse gefunden'), '');
            add_option_to_select_box(this.course_select_box, option);
            this.course_select_box.disabled = true;
        }
        else {
            this.course_select_box.disabled = false;
        }
        
        this.update_active_step(this.course_select_box.step_num);
    };
    
    /*
        Function: fill_accommodation_forms
            fills the select box with 
            accommodation forms received from the server.      
    */
    this.fill_accommodation_forms = function ( an_accommodation_form_set )
    {
        var please_choose_an_accommodation_option = new Option( gettext( 'Bitte wähle eine Unterkunft:'), '' );                        
        
        this.fill_select_box ( an_accommodation_form_set,
                          this.accommodation_form_select_box,
                          'id', 'name',
                          [ please_choose_an_accommodation_option ],
                          true /* set_if_only_one_option */ );
    };                      

    /*
        Function: fill_price_periods
            fills the select box with 
            price periods received from the 
            save_course_accommodation_form_prices function.  
    */
    this.fill_price_periods = function(a_price_periods_set)
    {
        // Get text representation of periods
        for ( var i = 0; i < a_price_periods_set.length; i ++ )
        {
            var a_price_period = a_price_periods_set[i];
            var from_date_text = date_str_to_i18n_date(a_price_period .from_date, 'd.My');
            var to_date_text = date_str_to_i18n_date(a_price_period .to_date, 'd.My');
            
            a_price_period.interval_text= from_date_text + ' - ' + to_date_text;
        }
        
        var preselectSinglePeriod = true; // preselect entry, if num(entries) == 1
        this.fill_select_box(
            a_price_periods_set,
            this.course_season_select_box,
            'from_date', 
            'interval_text',
            [ new Option(gettext('Dein Kurs ist am:'), '') ],
            preselectSinglePeriod);
        
        // fill the new seasons into school demonstrator
        this.school_demonstrator.fill_seasons(a_price_periods_set);
    };
    
    /*
        Function: fill_course_weeks
            finds out which weeks are available in the course price list 
            and fills course weeks select box with options.   
    */
    this.fill_course_weeks = function ( a_from_date )
    {
        var weeks_available_set = [];
        /*
            Find the course price list:            
        */
        var current_course_price_list = this.get_course_prices( a_from_date );                                                
        
        /*
            Have we found a suitable course price?            
        */
        if ( current_course_price_list )
        {
            /*
                Now find which weeks are available:            
            */                    
            var max_weeks = this.get_max_weeks ( current_course_price_list );                
            
            var weeks_available = [];
            
            /*
                Check weeks from 1 to 24:                
            */
            for ( var i = 1; i < max_weeks+1; i ++ )
            {                    
                if ( this.get_week_price(/* price list*/ current_course_price_list, /* how many weeks */ i) )
                {
                    /*
                        There is an entry for i number of weeks!
                    */
                    weeks_available.push( i );
                }
            }
              
            /*
                Make set out of them to suit the fill_select_box:            
            */                        
            weeks_available_set = [];
            for ( i = 0; i < weeks_available.length; i++ )
            {
                var week_entry = {};
                week_entry.value = weeks_available[i];
                week_entry.text = weeks_available[i] + ' ';

                if ( weeks_available[i] === 1 )
                {
                    week_entry.text += gettext ( 'Woche' );
                }
                else
                {
                    week_entry.text += gettext ( 'Wochen' );
                }
                
                weeks_available_set.push( week_entry );
            }                                
        } 
        
        /*
            Fill the weeks available:                
        */
        var please_choose_course_weeks_option = new Option( gettext('Kurs - Wie viele Wochen?'), '');
        
        this.fill_select_box ( weeks_available_set,
                               this.course_weeks_select_box,
                               'value', 'text',
                               [ please_choose_course_weeks_option ],
                               true /* set_if_only_one_option */ );
    };
    
    /**
     * Function: fill_accommodation_weeks
     *       Finds available week numbers in the course price list 
     *       and fills course weeks select box.
     *       Condition: max(accommodation_weeks) <= course_weeks
     * @param {Date} a_from_date
     */
    this.fill_accommodation_weeks = function(a_from_date)
    {
        var weeksSet = [];
            
        /*
            Find the course price list:            
        */
        var accommodationPrices = this.get_accommodation_prices(a_from_date);
        
        /*
            Have we found a suitable course price?
        */
        if (accommodationPrices)
        {
            /*
                Now find which weeks are available:            
            */                    
            var maxWeeks = this.get_max_weeks(accommodationPrices);
            
            // ensure max(accommodation_weeks) <= current_course_weeks
            if (maxWeeks > this.course_weeks)
            {
                maxWeeks = this.course_weeks;
            }
            
            /*
                Check weeks from 1 to 24:                
            */
            var weeksAvailable = [];
            for (var i = 1; i < maxWeeks+1; i ++)
            {                    
                if ( this.get_week_price(/* price list*/ accommodationPrices, /* how many weeks */ i) )
                {
                    /*
                        There is an entry for i number of weeks!
                    */
                    weeksAvailable.push(i);
                }
            }
               
            /*
                Create a set for the select_box:            
            */
            for ( i = 0; i < weeksAvailable.length; i++ )
            {
                var entry = {};
                entry.value = weeksAvailable[i];
                entry.text = weeksAvailable[i] + ' ';

                if (weeksAvailable[i] === 1 )
                {
                    entry.text += gettext('Woche');
                }
                else
                {
                    entry.text += gettext('Wochen');
                }
                
                weeksSet.push(entry);
            }                                
        } 
        
        var firstOption = new Option( gettext('Unterkunft - Wie viele Wochen?'), '');
        var selectIfSingleOption = true;
        this.fill_select_box( weeksSet,
                              this.accommodation_weeks_select_box,
                              'value', 
                              'text',
                              [ firstOption ],
                              selectIfSingleOption );
    };
         
    /*
        Function: fill_transfer
            Fills the transfer requested select box.
    */
    this.fill_transfer = function(transfer_set)
    {
        this.transfer_select_box.options.length = 0;
        
        // transfer is only bookable if an accommodation is booked too
        var accommodation_booked = (this.accommodation_form !== this.void_accommodation_form);
        
        if (accommodation_booked && this.school_transfer_set.length > 0)
        {
            var firstOption = new Option( gettext('Wähle Transfer:'), '');
            var options = [];
            
            for (var j=0; j<this.school_transfer_set.length; j++)
            {
                var an_option = { 
                    value: this.school_transfer_set[j].id, 
                    text: this.school_transfer_set[j].name 
                };
                options.push(an_option);
            }
            
            /*
                Fill the options:
            */                                
            this.fill_select_box(options,
                                 this.transfer_select_box,
                                 'value', 'text',
                                 [firstOption] );
        }
        else
        {                
            /*
                There are no options,
                just set corresponding property to false, 
                style it and enable children:
            */
            this.transfer_select_box.style.disabled = true;
            var notAvailableOption = new Option( gettext('Transfer nicht verfügbar'), '0' );
            
            add_option_to_select_box( this.transfer_select_box,
                                      notAvailableOption,
                                      notAvailableOption.value );
            /*
                Set it:
            */ 
            this.set_transfer( notAvailableOption.value );
        }    
    };    
    
    /**
     * Function: fill_seasons
     *     Fills the seasons select box
     *     
     *       Checks if course and accommodation price sets are available
     *       
     *       Updates the price periods according to all price sets we have at our disposal.            
     *       
     *       Enables child elements and updates the user interface
     *       
     *       If course prices and accommodation prices are not available, nothing will be done.
     */
    this.fill_seasons = function() 
    {
        if (this.course_price_set &&
            this.school_inscription_fee_set &&
            xor(this.accommodation_price_set, this.accommodation_form === this.void_accommodation_form) )
        {
            // Intersect periods
            var intersectionSets = [];
            intersectionSets.push(this.course_price_set);
            intersectionSets.push(this.school_inscription_fee_set);
            
            // add transfer if available
            if (this.transfer > 0)
            {
                intersectionSets.push(this.school_transfer_price_set);
            }
            
            // Add accommodation price set if an accommodation form is selected
            if (this.accommodation_form !== this.void_accommodation_form)
            {
                intersectionSets.push(this.accommodation_price_set);
            }            
            
            /*
             * Check whether there exist different price periods for
             * course prices, inscription fees, transfer or accommodations
             */
            var ignorePast = true; /* ignore periods with to_date before today */
            this.price_periods = intersect_periods_of_owners(intersectionSets, ignorePast, this.today);
            this.fill_price_periods(this.price_periods);
            
            // If only one interval available, preselect this one
            if (this.price_periods.length > 1)
            {
                this.course_season_tmp = null;
            }
            else if (this.price_periods.length === 1)
            {
                this.course_season_tmp = this.price_periods[0].from_date;
            }
        }
    };
       
    /*
        Function: fill_select_box
            his function fills the select box with set received from the server.                  
            
        Parameters:
            a_set - option set
            a_select_box - select box element
            value_attribute - specifies which attribute to use as value for an option.
            caption_attribute - specifies which attribute to use as caption.                       
            please_choose_options_array - All this options are inserted at the beginning. (optional), elements are directly inserted into the DOM, please supply copies if you insert the same elements in other locations
            set_if_only_one_option - If true and there is only one option, it will be automatically set. OnChange event will be called.
    */
    this.fill_select_box = function ( a_set, 
                                      a_select_box, 
                                      value_attribute, 
                                      caption_attribute,
                                      please_choose_options_array,
                                      set_if_only_one_option )
    {
        var i = 0;
        var j = 0;
        var option = null;
        
        // Disable object, enable it later, if needed
        //this.disable_obj ( a_select_box );                 
        
        if (a_set.length)
        {                   
            // Clear all existing options
            a_select_box.options.length = 0;
                                    
            if (please_choose_options_array)
            {
                // Insert 'please choose' options
                for (i = 0; i < please_choose_options_array.length; i++ )
                {
                    option = please_choose_options_array[i];
                    add_option_to_select_box(a_select_box, option);
                }
            }
            
            // Insert entries
            for (j = 0; j < a_set.length; j ++ )
            {
                create_and_add_option_to_select_box(
                    a_select_box,
                    a_set[j][caption_attribute],
                    a_set[j][value_attribute]);
            }                  
                                             
            /*
                Check if we have only one option 
                and if we would like to set it:
            */                        
            if (set_if_only_one_option && a_set.length === 1)
            {
                // The option with index 0 is a 'please choose'
                var an_index_to_set = 0;
                
                if (please_choose_options_array)
                {
                    an_index_to_set = please_choose_options_array .length;
                }
                
                a_select_box.selectedIndex = an_index_to_set;
                                               
                if (a_select_box.set_function)
                {
                    var base_object  = a_select_box.set_function.base_object;
                    var function_str = a_select_box.set_function.function_str;
                    base_object[function_str]( a_select_box.value );
                }
                
                this.set_inactive(a_select_box);
            }
            
            // Enable the select box
            this.enable_obj(a_select_box);
        }
    };
    
    /*
        Function: fill_cell
            enables the given cell
            and fills it with content given in 'a_text'
    */
    this.fill_cell = function ( a_cell, a_text )
    {
        a_cell.innerHTML = a_text;
        this.enable_obj(a_cell);
    };
    
    /*
        Function: enable_obj
            - If an_obj has a setDisabled function, it will be prefered.
            - If an_obj is a select box, it enables it.
            - If it is a span, it makes it visible.
            - If it is a table row, it makes it visible.
            - If it is a table cell, it makes it visible.
            - If it is a button, it enables it.
            - If it is a checkbox, it enables it.
    */
    this.enable_obj = function ( an_obj )
    {
        /*
            If an_obj has a setDisabled function,
            it will be prefered.
            
            If an_obj is a select box, it enables it.
            
            If it is a span, it makes it visible.
            
            If it is a table row, it makes it visible.
            
            If it is a table cell, it makes it visible.
            
            If it is a button, it enables it.
            
            If it is a checkbox, it enables it.
        */
        if ( an_obj.setDisabled )
        {            
            an_obj.setDisabled ( false );
        }
        else if ( an_obj.nodeName === 'SELECT' )
        {
            an_obj.disabled  = false;
        }
        else if ( an_obj.nodeName === 'SPAN' )
        {
            an_obj.style.display = '';
        }
        else if ( an_obj.nodeName === 'TR' )
        {
            an_obj.style.display = '';
        }  
        else if ( an_obj.nodeName === 'TD' )
        {
            an_obj.style.display = '';
        }     
        else if ( an_obj.nodeName === 'INPUT' )
        {
            if ( an_obj.type === 'button' )
            {
                an_obj.disabled = false;
            }
            else if ( an_obj.type === 'checkbox' )
            {
                an_obj.disabled = false;
            }
        }
        if (an_obj.nodeName === 'A')
        {
            an_obj.style.display = '';
        }
    };
    
    /*
        Function: enable_only_direct_obj_children
            enables all select boxes specified 
            in children_select property of a_select_box.   
    */
    this.enable_only_direct_obj_children = function ( an_obj )
    {
        var i = 0;
        
        if ( an_obj.children_elements !== undefined )
        {
            for (i = 0; i < an_obj.children_elements.length; i ++ )
            {
                this.enable_obj ( an_obj.children_elements [ i ] );
            }
        }
    };

    /*
        Function: disable_obj.
            Disables an object
            - If it has a setDisabled function, it will be prefered.
            - If an_obj is a select box, it disables it.
            - If it is a span, it makes it invisible.
            - If it is a table row, it makes it invisible.
            - If it is a table cell, it makes it invisible.
            - If it is a button, it disables it.
            - If it is a checkbox, it disables it and sets it to off.
            - If exists, a corresponding property will be set to null.
    */
    this.disable_obj = function ( an_obj )
    {
		if (an_obj == null)
		{
			return; // dont do anything
		}
		
        if ( an_obj.setDisabled )
        {
            an_obj.setDisabled ( true );
        }
        else if ( an_obj.nodeName === 'SELECT' )
        {
			var optionText = null;
			
			switch (an_obj.id)
			{
				case "id_price_calculator_select_course":
					optionText = gettext('Kurs');
					break;
					
				case "id_price_calculator_select_accommodation_form":
					optionText = gettext("Unterkunftsform");
					break;
					
				case "id_price_calculator_select_transfer":
					optionText = gettext("Transfer");
					break;
					
				case "id_price_calculator_select_course_season":
					optionText = gettext("Saison");
					break;
					
				case "id_price_calculator_select_course_weeks":
					optionText = gettext("Kursdauer");
					break;
			}
				
            an_obj.innerHTML = '<option>' + optionText + '</option>';
            an_obj.disabled  = true;
            this.set_inactive(an_obj);
        }
        else if ( an_obj.nodeName === 'SPAN' )
        {
            an_obj.style.display = 'none';
        }      
        else if ( an_obj.nodeName === 'TR' )
        {
            an_obj.style.display = 'none';
        }  
        else if ( an_obj.nodeName === 'TD' )
        {
            an_obj.style.display = 'none';
        }             
        else if ( an_obj.nodeName === 'INPUT' )
        {
            if ( an_obj.type === 'button' )
            {
                an_obj.disabled = true;
            }
            else if ( an_obj.type === 'checkbox' )
            {
                an_obj.checked  = false;                    
                an_obj.disabled = true;
            }
        }
        else if (an_obj.nodeName === 'A')
        {
            an_obj.style.display = 'none';
        }
        
        /*
            Set all corresponding properties to null:
        */
        this.clear_properties ( an_obj );
    };    

    /*
        Function: disable_obj_children
            Traverses all children recursevly and disables them.            
            
            Omit_this_one instructs the function to omit the given select box.
    */
    this.disable_obj_children = function ( an_obj )
    {
		if (an_obj == null)
		{
			return; // don't do anything
		}
        if ( an_obj.children_elements !== undefined )
        {
            /*
                Proceed recursevly:                
            */
        	var i = 0;
            for (i = 0; i < an_obj.children_elements.length; i ++ )
            {                
                this.disable_obj(an_obj.children_elements[i]);
                this.disable_obj_children(an_obj.children_elements[i]);
            }
        }
    };
        
    /*
        Function: clear_properties
            Sets all corresponding properties to null.
    */
    this.clear_properties = function( an_obj )
    {
        var i = 0;
        var property = null;
        
        if (an_obj.properties)
        {
            for (i = 0; i < an_obj.properties.length; i ++ )
            {
                property = an_obj.properties[i];
                this[property] = null;
            }
        }    
    }; 
   
    /**
     * Searches the array for an object with object.id = an_id
     * @param {Object} an_id
     * @param {Object} an_array
     * @return Object with id == an_id, Null if no object is found
     */
    this.find_obj_with_id = function ( an_id, an_array )
    { 
        var result = null;
        var i = 0;
        
        for (i = 0; i < an_array.length; i ++ )
        {
            if ( an_array[i].id == an_id )
            {
                result = an_array[i];
                break;
            }
        }  
        return result;
    };
      
               
    /*
        ---------------------------
        Request /receive functions:
        ---------------------------
    */               
    
    /*
        POST Request templates:
            obj_id - Int, object identifier
            app_name - String, django application name
            model_name - String, django model name
            children_set_name - String, django relation name
            fetch_only_these_fields - JSON String, array of model fields
    */
    
    this.city_set_request = function( country_id )
    {
        var request = {
            obj_id:                  country_id,
            app_name:                'destinations', 
            model_name:              'Country',
            children_set_name:       'city_set', 
            fetch_only_these_fields: dojoWrapper.serializeToJson(['id', 'name'])
        };
		
        return request;
    };
    
    this.school_set_request = function( school_id )
    {
        var request = {
            obj_id:                  school_id,
            app_name:                'destinations', 
            model_name:              'City',
            children_set_name:       'school_set', 
            fetch_only_these_fields: dojoWrapper.serializeToJson(['id', 'name'])
        };
        return request;
    };
    
    this.school_content_request = function (school_id)
    {
        var request = {    
            obj_id:                  school_id,
            app_name:                'db_models', 
            model_name:              'School',
            children_set_name:       '',    /* we want the school, not a children set!*/
            fetch_only_these_fields: dojoWrapper.serializeToJson(['id', 'name', 'currency', 'transfer_availability'])
        };
        return request;
    };
    
    this.course_set_request = function (school_id)
    {
        var request = {
            obj_id:                  school_id,
            app_name:                'db_models', 
            model_name:              'School',
            children_set_name:       'course_set',  
            fetch_only_these_fields: dojoWrapper.serializeToJson([ 'id', 'name', 'type' ])
        };
        return request;
    };
    
    this.accommodation_set_request = function (school_id)
    {
        var request = {
            obj_id:                  school_id,
            app_name:                'db_models', 
            model_name:              'School',
            children_set_name:       'accommodation_form_set',
            fetch_only_these_fields: dojoWrapper.serializeToJson([ 'id', 'name' ])
        };
        return request;
    };
    
    this.inscription_fee_set_request = function (school_id)
    {
        var inscription_fee_set_request = {
            obj_id:                  school_id,
            app_name:                'db_models', 
            model_name:              'School',
            children_set_name:       'school_inscription_fee_set',  
            fetch_only_these_fields: dojoWrapper.serializeToJson([ 'id', 'from_date', 'to_date', 'fee' ])
        };
        return inscription_fee_set_request;
    };
    
    this.transfer_set_request = function (school_id)
    {
        var request = {
            obj_id:                  school_id,
            app_name:                'db_models', 
            model_name:              'School',
            children_set_name:       'school_transfer_set',  
            fetch_only_these_fields: dojoWrapper.serializeToJson([ 'id', 'name', 'description' ])
        };
        return request;
    };
    
    this.transfer_price_request = function (transfer_id)
    {
        var request = {
            obj_id:                  transfer_id,
            app_name:                'db_models', 
            model_name:              'School_transfer',
            children_set_name:       'school_transfer_price_set',  
            fetch_only_these_fields: dojoWrapper.serializeToJson([ 'id', 'from_date', 'to_date', 'cost'])
        };
        return request;
    };
    
    this.course_price_request = function (course_id)
    {
        var request = {
            obj_id:                  course_id,
            app_name:                'db_models', 
            model_name:              'Course',
            children_set_name:       'course_price_set',  
            fetch_only_these_fields: dojoWrapper.serializeToJson([ ]) /* all fields are interesting!*/
        };
        return request;
    };
    
    this.accommodation_price_request = function (accommodation_form_id)
    {
        var request = {
            obj_id:                  accommodation_form_id,
            app_name:                'db_models', 
            model_name:              'Accommodation_form',
            children_set_name:       'accommodation_price_set',  
            fetch_only_these_fields: dojoWrapper.serializeToJson([ ]) /* all fields are interesting!*/ 
        };
        return request;
    };
    
    this.material_fee_request = function (school_id)
    {
        var request = {
            obj_id:                  school_id,
            app_name:                'db_models', 
            model_name:              'School',
            children_set_name:       'school_material_fee_set',  
            fetch_only_these_fields: dojoWrapper.serializeToJson([ ]) /* all fields are interesting!*/ 
        };
        return request;
    };
    
    /**
     * Function: send_school_request
     *       Sends a request for school information for the given school
     *       
     * @param {Int} a_school_id School identifier
     */
    this.send_school_request = function ( a_school_id )
    {
        /*
                Set values that we are 
                sending requests for to null
        */
        this.school                       = null;
        this.course_set                   = null;
        this.accommodation_form_set       = null;
        this.school_inscription_fee_set   = null;
        this.school_transfer_set    	  = null;
		
        /*
            Send request for the school:                
        */                                
        this.send_request( this.school_content_request(a_school_id), this, 'save_school_sets');
        
        /*
            Get courses and accommodation forms: 
        */                                            
        this.send_request( this.course_set_request(a_school_id), this, 'save_school_sets');            
        this.send_request( this.accommodation_set_request(a_school_id), this, 'save_school_sets');
        
        /*
          Get additional fees and costs
        */					
        this.send_request( this.inscription_fee_set_request(a_school_id), this, 'save_school_sets');
        this.send_request( this.transfer_set_request(a_school_id), this, 'save_school_sets');
        this.send_request( this.material_fee_request(a_school_id), this, 'save_school_sets');
    }; 
   
    /**
     * Function: send_request_for
     *       Sends a request for a given object.
     *       
     *       When response arrives, it will call a_func with ( type, data ) arguments.
     *       
     *       If package is already available, it will just forward it to this.receive_response. 
     *
     * @param {Object} request
     * @param {Object} a_self
     * @param {Object} save_func_str
     */
    this.send_request = function ( request, a_self, save_func_str )
    {
		
        /*
            Let the user know we are doing something:            
        */
        a_wait_cursor_manager.push_pending_job_signal();
        // New for yalea
		var request_content_str = dojoWrapper.serializeToJson ( request );  
		
		
		
        /*
            Do we have a cached response?
        */
        if (this.cached_responses[request_content_str]) 
		{
			var a_cached_response = this.cached_responses[request_content_str];
			var data = copy_an_object(a_cached_response);
			this.receive_response(data, a_self, save_func_str);
		}
		/*
 		We have to request it from server:
 		*/
		else 
		{
			/*
						 We have to request the package:
						 */
			/*
	 we have to make receive_response somehow global,
	 because handle function refers to it:
	 */		
			var receive_response = this.receive_response;
			var cached_responses = this.cached_responses;
			var handle_errors = this.handle_transmit_errors;
			
			/*
	 Send a request:
	 */
			var agent = function(aData, aArgs)
			{
				receive_response(aData, a_self, save_func_str, cached_responses, request_content_str);
			}
			dojoWrapper.ajaxRequestPost(this.url_fetch_obj, request, agent);
		}
		
            
    };
    
    /**
     * Function: receive_response
     *       Callback function for ajax requests
     *       Decodes the JSON string and invokes the function passed in parameters
     *       Caches the response if no errors occurred
     *
     * @param {Object} data Received data
     * @param {Object} a_self Reference to current object
     * @param {String} a_func_str Function that should be called
     * @param {Hashtable} cached_responses Cache
     * @param {String} a_request_content_str Request
     */
    this.receive_response = function ( data, 
                                       a_self, 
                                       a_func_str,
                                       cached_responses,
                                       a_request_content_str )
    {              
        /*
            Let the user know we are finished:            
        */            

        a_wait_cursor_manager.pop_pending_job_signal();
        
        /*
            Unpack the package: 
            Just check if it's already an object
        */        
		
		
        var a_package = null;
        if (data.errors !== undefined)
        {
            a_package = data;
        }
        else
        {
			if ( typeof ( data ) == "string" )
			{
				a_package = dojoWrapper.evalFromJson( data );
			}
			else if ( typeof ( data ) == "object" )
			{
				a_package = data;
			}
			else
			{
				console.error ( "price_calculator_class.receive_response (): data format not recogniyed" + data);
			}

        }
        
        /*
            Check for errors    
        */                       
        if ( a_package.errors != undefined &&
             a_package.errors != null &&
             a_package.errors != '' )
        {
            show_errors(a_package.errors);
        }
        else
        {
            // Cache the response only if no error occurred
            if (a_request_content_str && cached_responses )
            {      
                cached_responses[a_request_content_str] = data;           
            }
        
            // Call the function
            if ( !a_self[a_func_str] )
            {
                show_errors( ['Function: ' + a_func_str + ' does not exist.' ] );
            }
            else
            {
                a_self[a_func_str](a_package);
            }                
        }        
		
    };
    
    /**
     * Function: handle_transmit_errors
     *       Callback function for ajax request errors
     *
     * @param {Object} type
     * @param {Object} error
     */
    this.handle_transmit_errors = function ( type, error )
    {
        a_wait_cursor_manager.pop_pending_job_signal();
        //document.body.style.cursor = 'default';
        show_errors([error]);
    };
    
    /**
     * Saves a json object as string into cache
     * @param {Object} request Request Content
     * @param {Object} data Reply package
     */
    this.save_to_cache = function(request, data)
    {
        var request_str = dojoWrapper.serializeToJson(request);
        this.cached_responses[request_str] = data;
    };
    
    
    /**
     * Function: init
     *       Initializes class variables
     */
    this.init = function ()
    {
        /*
            We've already prefetched some packages:            
        */                      
        this.fill_countries(prefetched_packages.country_set);        
        
        /* initialize the first step */
        this.update_active_step(1);
        if (country_id)
        {
            this.save_to_cache(this.city_set_request(country_id), prefetched_packages.city_set);
            // select predefined country
            if (this.country_set)
            {
                this.set_country(country_id);
            }
        }
        
        if (city_id && country_id)
        {
            this.save_to_cache(this.school_set_request(city_id), prefetched_packages.school_set);
            
            // Select predefined city
            if (this.city_set)
            {                
                this.set_city(city_id);
            }
        }
        
        if (school_id)
        {
            //this.save_to_cache(this.inscription_fee_set_request(school_id), prefetched_packages.inscription_fee);
            //this.save_to_cache(this.transfer_set_request(school_id), prefetched_packages.school_set);
                        
            // Select predefined school
            if (this.school_set)
            {
                this.set_school(school_id);
            }                                  
        }
    };
    
    this.init();
}
