// ukljuci headere za windows API
#include <windows.h>
#include <windowsx.h>
#include <d3d9.h>

// ukljuci Direct3D library
#pragma comment (lib, "d3d9.lib")

// globalne deklaracije
LPDIRECT3D9 d3d;    // pointer na D3D9 sucelje
LPDIRECT3DDEVICE9 d3ddev;    // pointer na klasu uredjaja

// prototipi funkcija
void initD3D(HWND hWnd);    // inicijaliziraj D3D9
void render_frame(void);    // renderiraj frame
void cleanD3D(void);    // zatvori Direct3D i otpusti resurse

// prototip funkcija WindowProc za obradu poruka
LRESULT CALLBACK WindowProc(HWND hWnd,
                         UINT message,
                         WPARAM wParam,
                         LPARAM lParam);

// pocetak glavnog programa
int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow)
{
    // handle za prozor
    HWND hWnd;
    // struktura koja sadrzi opis novog prozora
    WNDCLASSEX wc;

    // resetiraj podatke u wc
    ZeroMemory(&wc, sizeof(WNDCLASSEX));

    // popuni opis prozora
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = WindowProc;
    wc.hInstance = hInstance;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
    wc.lpszClassName = L"WindowClass1";

    // registriraj klasu prozora
    RegisterClassEx(&wc);

    // kreiranje prozora
    hWnd = CreateWindowEx(NULL,
                          L"WindowClass1",    // naziv klase
                          L"DirectX početak",   // naslov na prozoru
                          WS_OVERLAPPEDWINDOW,    // stil prozora (ispred svih)
                          300,    // x-pozicija
                          300,    // y-pozicija
                          500,    // duljina prozora
                          400,    // visina prozora
                          NULL,    // nema prozora roditelja, NULL
                          NULL,    // ne koristi se izbornik, NULL
                          hInstance,    // handle za aplikaciju
                          NULL);    // ne koristi se s vise prozora, NULL

    // prikazi prozor na ekranu
    ShowWindow(hWnd, nCmdShow);

    // kreni u glavnu petlju:

    // struktura koja sadrzi podatke o poruci
    MSG msg;

	initD3D(hWnd);

	while(TRUE)
	{
		// provjeri postoji li poruku u redu cekaja
		while(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
		{
			// prevedi poruku i posalji je na obradu WindowProc()
			TranslateMessage(&msg);
			DispatchMessage(&msg);
		}

		// ako je poruka WM_QUIT, izadji iz petlje
		if(msg.message == WM_QUIT)
			break;

		// Ovdje se izvrsava Direct3D kod
		render_frame();
	}

	cleanD3D();

    // vrati poruku o izlazu WM_QUIT windowsima
    return msg.wParam;
}

// funkcija koja je glavni upravitelj porukama u programu
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    // saznaj o kakvoj se poruci radi
    switch(message)
    {
        // ako je prozor zatvoren
        case WM_DESTROY:
            {
                // zatvori aplikaciju
                PostQuitMessage(0);
                return 0;
            } break;
    }

    // upravljanje sistemskim porukama koje switch nije obradio
    return DefWindowProc (hWnd, message, wParam, lParam);
}

// funkcija inicijalizira i priprema Direct3D za koristenje
void initD3D(HWND hWnd)
{
    d3d = Direct3DCreate9(D3D_SDK_VERSION);    // kreira Direct3D sucelje

    D3DPRESENT_PARAMETERS d3dpp;    // kreira strukturu koja sadrzi podatke o grafickoj

    ZeroMemory(&d3dpp, sizeof(d3dpp));    // obrisi strukturu
    d3dpp.Windowed = TRUE;    // program je u prozoru, nije fullscreen
    d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;    // odbaci stare frameove
    d3dpp.hDeviceWindow = hWnd;    // postavi da prozor koristi Direct3D

    //kreiraj D3D9 uredjaj orema parametrima u strukturi
    d3d->CreateDevice(D3DADAPTER_DEFAULT,
                      D3DDEVTYPE_HAL,
                      hWnd,
                      D3DCREATE_SOFTWARE_VERTEXPROCESSING,
                      &d3dpp,
                      &d3ddev);
}

// funkcija koja rendreira jedan frame (OpenGL iscrtaj!)
void render_frame(void)
{
    // obrisi prozor i stavi plavu pozadinu
    d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 40, 100), 1.0f, 0);

    d3ddev->BeginScene();    // zapocni 3D scenu

    // napravi 3D renderiranje na straznjem bufferu

    d3ddev->EndScene();    // zavrsi 3D scenu

    d3ddev->Present(NULL, NULL, NULL, NULL);    // prikazi frame
}

// funkcija brise Direct3D i COM
void cleanD3D(void)
{
    d3ddev->Release();    // zatvori i otpusti 3D uredjaj
    d3d->Release();    // zatvori i otpusti Direct3D
}