#ifndef Fenster_H
#define Fenster_H

#include "Objekt.h"
#include <Windows.h>

namespace Framework
{
	class Farbe; // farbe.h
	class TextFeld; // TextFeld.h
	class LRahmen; // Rahmen.h
	class Bildschirm; // Bildschirm.h
	class Schrift; // Schrift.h
	class Text; // Text.h
	class Punkt; // Punkt.h
	class Bild; // Bild.h
	class WFenster; // aus dieser Datei
	class WFensterArray; // aus dieser Datei

	// Erzeugen einer normalen Fensterklasse
	WNDCLASS F_Normal( HINSTANCE hInst );
	WNDCLASSEX F_NormalEx( HINSTANCE hInst );

	LRESULT CALLBACK WindowProc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam);
	// Startet eine Schleife, die die Benutzereingaben verarbeitet. Die Schleife läuft, bis irgendwo im Programm StopNachrichtenSchleife aufgerufen wird
	__declspec( dllexport ) void StartNachrichtenSchleife();
	// Stoppt die Ausführung der Nachrichten Schleife des Frameworks.
	//  hwnd: Ein Handle auf ein beliebiges Fenster des Frameworks, das Nachrichten empfangen kann. Wird benötigt, um eine Nachricht zu senden, damit die funktion StartNachrichtenSchleife nicht mehr wartet und sofort beendet wird
	__declspec( dllexport ) void StopNachrichtenSchleife( HWND hwnd );

	unsigned char VirtualZuChar( int Virtual );
	// Klasse für ein Fenster in Windows
	class WFenster
	{
	private:
		HWND hWnd; // Handel zum Fenster
		int style;
		bool (*MausAktion)( WFenster *, MausEreignis );
		void (*VSchließAktion)( WFenster * );
		void (*NSchließAktion)( WFenster * );
		bool (*TastaturAktion)( WFenster *, TastaturEreignis );
		Bildschirm *screen;
		int mx, my;
		bool verschiebbar;
		int ref;
		HWND rahmen;
		HBITMAP bitmap;
		HDC hdc;

	public:
		//--Konstruktor--
		WFenster();
		WFenster( HWND hWnd );
		//--Destruktor--
		~WFenster();
		// nicht constant
		void erstellen( int style, WNDCLASS wc ); // Das Fenster Erstellen
		void erstellenEx( int exStyle, int style, WNDCLASSEX wc ); // Das Fenster Erstellen
		void setAnzeigeModus( int mod ); // Zeigt das Fenster im übergebenen Modus an
		void setPosition( Punkt *pos ); // Bildschirmposition des Fensters setzen
		void setPosition( int x, int y );
		void setGröße( Punkt *größe ); // Die größe des Fensters setzen
		void setGröße( int breite, int höhe );
		void setBounds( Punkt *pos, Punkt *größe ); // Größe und Porition in einem
		void setBildschirm( Bildschirm *screen );
		void zerstören(); // Zerstört das Fenster
		void doMausAktion( MausEreignis *me ); // ruft MausAktion auf
		void doVSchließAktion(); // ruft VSchließAktion auf
		void doNSchließAktion(); // ruft NSchließAktion auf
		void doTastaturAktion( TastaturEreignis *et ); // ruft TastaturAktion auf
		void doRestoreMessage(); // macht den Rahmen sichtbar
		void setMausAktion( bool (*MausAk)( WFenster *, MausEreignis ) ); // setzt das MausEreignis
		void setVSchließAktion( void (*vSchließAk)( WFenster * ) ); // setzt v schließ Aktion
		void setNSchließAktion( void (*nSchließAk)( WFenster * ) ); // setzt n schließ Aktion
		void setTastaturAktion( bool (*TastaturAk)( WFenster *, TastaturEreignis ) ); // setzt das TastaturEreignis
		void setFensterHandle( HWND hWnd ); // setzt das operationsfenster
		void setVerschiebbar( bool verschiebbar ); // legt fest, ob das Fenster durch ziehen mit Maus verschoben werden kann
		void ladeRahmenFenster( Bild *zBild, HINSTANCE hinst ); // setzt einen Transpatenten Rahmen um das Fenster
		// constant
		HWND getFensterHandle() const; // gibt das Fenster Handle zurück
		Punkt *getPosition() const; // gibt die Fensterposition zurück
		Punkt *getGröße() const; // gibt die Fenstergröße zurück
		bool hatMausAktion() const; // Prüft, ob eine Aktion bei MausEreignis festgelegt wurde
		bool hatVSchließAktion() const; // Prüft, ob eine Aktion vor Fensterschließen festgelegt wurde
		bool hatNSchließAktion() const; // Prüft, ob eine Aktion nach Fensterschließen festgelegt wurde
		bool hatTastaturAktion() const; // Prüft, ob eine Aktion bei TastaturEreignis festgelegt wurde
		Bildschirm *getBildschirm() const;
		Bildschirm *zBildschirm() const;
		bool istVerschiebbar() const; // prüft, ob das Fenster durch ziehen mit Maus verschoben werden kann
		// Reference Counting
		WFenster *getThis();
		WFenster *release();
	};

	// Verwaltung der WFenster im Framework
	class WFensterArray
	{
	private:
		WFensterArray *next;
		WFenster *This;

	public:
		// Konstruktor 
		WFensterArray();
		// Destruktor 
		~WFensterArray();
		// add und remove 
		bool addFenster( WFenster *fenster );
		bool removeFenster( WFenster *fenster );
		WFensterArray* getNext();
		void setNext0();
		void del();
		// Messages 
		bool sendVSchließMessage( HWND hWnd );
		bool sendNSchließMessage( HWND hwnd );
		bool sendMausMessage( HWND hWnd, MausEreignis *me );
		bool sendTastaturMessage( HWND hwnd, TastaturEreignis *te );
		bool sendRestoreMessage( HWND hwnd );
		WFenster *getThis();
	};

	// WMessageBox
	void WMessageBox( HWND hWnd, Text *titel, Text *meldung, UINT style );
}
#endif