#ifndef OPENGL_H
#define OPENGL_H

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
#include <cstdlib> //m.in. exit

class COkno
{
private:
	bool ZmianaRozdzielczosci(long szerokosc, long wysokosc, long glebiaKolorow = 32) const;

protected:
	HWND uchwytOkna;
	long szerokoscObszaruUzytkownika;
	long wysokoscObszaruUzytkownika;

public:
	COkno() :uchwytOkna(NULL){};	
	bool Inicjuj(HINSTANCE uchwytAplikacji, POINT polozenieOkna, POINT rozmiarOkna, bool trybPelnoekranowy = false, bool zmianaRozdzielczosci = true);
	WPARAM Uruchom();
	LRESULT WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
};

#include "MacierzGL.h"
#include "Aktor.h"

enum TrybKontroliKamery { tkkFPP, tkkTPP, tkkArcBall, tkkModel };

class COknoGL : public COkno
{
private:
	HGLRC uchwytRC; //uchwyt kontekstu renderingu
	HDC uchwytDC; //uchwyt prywatnego kontekstu urządzenia GDI
	bool UstalFormatPikseli(HDC uchwytDC) const;
	bool InicjujWGL(HWND uchwytOkna);
	void UsuńWGL();	
	void UmieśćInformacjeNaPaskuTytułu(HWND uchwytOkna);

	//unsigned int vao;
	//unsigned int vbo[3];
	//void InicjujBuforWerteksów();
	//void UsuńBuforWerteksów();

	unsigned int idProgramuShaderow;
	static unsigned int KompilujShader(const char* nazwaPliku, unsigned int typ, bool trybDebugowania = false);
	static unsigned int PrzygotujShadery(const char* vsNazwaPliku, const char* fsNazwaPliku, bool trybDebugowania = false);	

protected:
	void UstawienieSceny(bool rzutowanieIzometryczne = false);
	void RysujScenę();

	Aktor** aktorzy;
	unsigned int liczbaAktorów;
	virtual unsigned int PrzygotujAktorów(); //zwraca liczbę aktorów
	virtual void RysujAktorów();
	virtual void UsuńAktorów();

	Macierz4 macierzŚwiata, macierzWidoku, macierzRzutowania, macierzNormalnych;
	
	typedef void (COknoGL::*TypMetodyObsługującejPrzesunięcieMyszy)(const POINT bieżącaPozycjaKursoraMyszy, const POINT przesunięcieKursoraMyszy);

	virtual void ObsługaKlawiszy(WPARAM wParam);
	void ObliczaniePrzesunięciaMyszy(const LPARAM lParam, const float próg, POINT& poprzedniaPozycjaKursoraMyszy, TypMetodyObsługującejPrzesunięcieMyszy MetodaObsługującaPrzesunięcieMyszy);
	virtual void ObsługaMyszyZWciśniętymLewymKlawiszem(const POINT bieżącaPozycjaKursoraMyszy, const POINT przesunięcieKursoraMyszy);
	virtual void ObsługaMyszyZWciśniętymPrawymKlawiszem(const POINT bieżącaPozycjaKursoraMyszy, const POINT przesunięcieKursoraMyszy);
	virtual void ObsługaRolkiMyszy(WPARAM wParam);

	Wektor3 PobierzPołożenieKamery(bool pomińObroty = false) const;
	float OdległośćKamery() const;
	TrybKontroliKamery trybKontroliKamery = tkkArcBall;
	void ModyfikujPołożenieKamery(Macierz4 macierzPrzekształcenia);

	bool swobodneObrotyKameryAktywne;
	virtual void SwobodneObrotyKamery(const bool inicjacja, const float początkowe_dx = 0, const float początkowe_dy = 0, const float współczynnikWygaszania = 0);

	bool animacjaAktywna;
	virtual void AnimujScenę();

	void UstawParametryŹródłaŚwiatła(Wektor3 położenie, Wektor4 światłoOtoczenia, Wektor4 światłoRozpraszane, Wektor4 światłoRozbłysku);
	void UstawParametryMateriału(Wektor4 światłoOtoczenia, Wektor4 światłoRozpraszane, Wektor4 światłoRozbłysku, float wykładnikRozbłysku);
	void UstawParametryOsłabieniaOświetlenia(bool włączone, Wektor3 współczynniki);

	const bool teksturowanieWłączone;
	int liczbaTekstur;
	GLuint* indeksyTekstur;
	void PrzygotujTekstury(unsigned int liczbaTekstur, char** nazwyPlikówTekstur);
	void UsuńTekstury();

public:
	COknoGL() :COkno(), uchwytRC(NULL), uchwytDC(NULL), 
		macierzŚwiata(Macierz4::Jednostkowa), 
		macierzWidoku(Macierz4::Jednostkowa), 
		macierzRzutowania(Macierz4::Jednostkowa),
		macierzNormalnych(Macierz4::Jednostkowa),
		swobodneObrotyKameryAktywne(false), animacjaAktywna(false),
		teksturowanieWłączone(true) {};
	LRESULT WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
} okno;

typedef void (COknoGL::*MetodaObsługującaPrzesunięcieMyszy)(POINT bieżącaPozycjaKursoraMyszy, POINT przesunięcieKursoraMyszy);

#endif
