/**
 * $Id$
 * $Revision$
 * $Author$
 * $Date$
 *
 * This file is part of The iWear Framework.
 * In particular this file is part of the Framework Griffin
 *
 * The iWear Framework is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by the
 * Free Software Foundation as in version 2 of the License.

 * 
 * The iWear Framework is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
 * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * The iWear Framework; if not, write to the Free Software Foundation, Inc., 59
 * Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef __DISPLAY_H
#define __DISPLAY_H

// Standard includes
#include <stdlib.h>

// iWear includes
#include <iwear/stopwatch.h>
#include <iwear/thread.h>
#include <iwear/threadlocked.h>
#include <iwear_output/outputdata.h>
#include <iwear_output_griffin/griffinoutputdatafunctor.h>

#include <iwear_output_griffin/displayhandlerimagedata.h>
#include <iwear_output_griffin/displayhandlermenudata.h>
#include <iwear_output_griffin/displayhandlertextdata.h>
#include <iwear_output_griffin/displayhandlerwidgetdata.h>

#include <iwear_output_griffin/layoutmanager.h>

// Other includes
#include <SDL/SDL.h>
#include <SDL/SDL_thread.h>
#include <SDL/SDL_ttf.h>
#include <SDL/SDL_image.h>
#include <SDL/SDL_rotozoom.h>
#include <SDL/SDL_imageFilter.h>


namespace iwear{
namespace output{


/**
 * Display class
 * @author Carsten Rachuy
 */
class Display : public ThreadLocked {


 public:
    
    /**
     * Constructor
     */
    Display(Configuration& configuration);
    
    /**
     * Destructor
     */
    ~Display(void);

    /**
     * Init-method
     */
    void init(void);

    /**
     * Handle method
     * We can be sure, that we can work on these data objects as we
     * like. We should in this method parse everything and be prepared
     * to display it
     */
    void handle(OutputData* output_data);
    
    /**
     * Discard method
     * In this method we get rid of everything... As soon as it is
     * safe to delete the object we'll return...
     */
    void discard(OutputData* output_data);

    /**
     * Set focus to tha applicatuion
     */
    void switch_focus_to(const uid& application_id);

    /**
     * Handles events and distruibutes it to the handlers
     */
    void handle_event(      OutputData*                 output_data,
		      const OutputDataFunctorParameter& parameter   );

    /**
     * Call render on all display handlers
     */
    void render(void);


    /**
     * Set the state of the display thread to the given value
     */
    inline void set_running_to(bool running){
	ThreadLocker tl(Mutex);
	this->running = running;
    }


    /**
     * @returning the state of the display thread
     */
    inline bool is_running(void) const {
	ThreadLocker tl(Mutex);
	return this->running;
    }


    /**
     * Returns the nuber ob output data which can simultaniously be
     * displayed by griffin.
     */
    inline uint32_t get_number_of_displayable_output_data(const string& type) const {
	if (type == ImageData::TYPE){
	    return this->display_handler_image_data->get_number_of_displayable_output_data();
	} else
	if (type == MenuData::TYPE){
	    return this->display_handler_menu_data->get_number_of_displayable_output_data();
 	} else
	if (type == TextData::TYPE){
	    return this->display_handler_text_data->get_number_of_displayable_output_data();
	} else
	if (type == WidgetData::TYPE){
	    return this->display_handler_widget_data->get_number_of_displayable_output_data();
	} else {
	    return 0;
	}
    }



 private:

    /**
     * Configuration
     */
    Configuration& configuration;

    /**
     * Image display handler
     */
    DisplayHandlerImageData* display_handler_image_data;

    /**
     * Menu display handler
     */
    DisplayHandlerMenuData* display_handler_menu_data;

    /**
     * Text display handler
     */
    DisplayHandlerTextData* display_handler_text_data;

    /**
     * Widget display handler
     */
    DisplayHandlerWidgetData* display_handler_widget_data;

    /**
     * Map for holding the handlers
     */
    map<const string, DisplayHandler*> display_handler;


    /**
     * Image render area
     */
    //SDL_Rect* image_area;

    /**
     * Menu render area
     */
    //SDL_Rect* menu_area;

    /**
     * Text render area
     */
    //SDL_Rect* text_area;

    /**
     * Widget render area
     */
    //SDL_Rect* widget_area;



    /**
     * This variable is being set to 'true' if anything goes
     * wrong during the initialisation of SDL.
     * According to this variable the display can be set to some kind
     * of 'failsafe' setting. Ugly but functional or something like
     * this...
     */
    bool in_error_mode;
  
    /**
     * This variable defines whether the display thread should run
     */
    bool running;

    /**
     * The SDL surface for the background
     */
    SDL_Surface* background;

    /**
     * The SDL surface for the main screen
     */
    SDL_Surface* screen;

    /**
     * The SDL_Thread
     */
    SDL_Thread* sdl_thread;

    /**
     * The layout manager
     */
    LayoutManager* layout_manager;

    /**
     * Active application id
     */
    uid active_application_id;


};

} // namespace output
} // namespace iwear

#endif // __DISPLAY_H

