/*
Plik naglowkowy zawiera definicje i implementacje funkcji odpowiedzialnych
za obsluge listy wynikow.

           autor: r.Q
           licencja: GNU GPL

Lista ma nastepujaca strukture:
      
                         POZIOM: LATWY
      ----------------------------------------------------------------------
      TRYB MALO:
           1.Brak                                   0
           2.Brak                                   0
           3.Brak                                   0
           4.Brak                                   0
           5.Brak                                   0
      TRYB SREDNIO
           1.Brak                                   0
           2.Brak                                   0
           3.Brak                                   0
           4.Brak                                   0
           5.Brak                                   0
      TRYB DUZO:
           1.Brak                                   0
           2.Brak                                   0
           3.Brak                                   0
           4.Brak                                   0
           5.Brak                                   0
*/
#include <stdlib.h>
#include <string.h>

#ifndef _LISTA_H_
#define _LISTA_H_

#define MAX_LISTA 45     // maksymalna ilosc pozycji na liscie
#define LEN_TRUD  15     // ilosc pozycji na poszczegolnym poziomie trudnosci
#define LEN_TRYB   5     // ilosc pozycji w pojedynczym trybie
enum POZ_TRUD {LATWY, SREDNI, TRUDNY};   // sa trzy poziomy trudnosci
enum TRYB {T25K, T50K, T95K};            // sa takze trzy tryby gry, w zaleznosci
                                         // od ilosci koralikow

typedef struct {                         // struktura opisuje pojedynczy element tabeli wynikow
        char nazwa[10];
        unsigned int punkty;
        } POZYCJA;

POZYCJA* PobierzDane();
void OdczytajTryb(HDC, POZYCJA*, POZ_TRUD, TRYB, int, int, int, int);
void OdczytajPozTrud(HDC, POZYCJA*, POZ_TRUD);
void AktualizujTabele(HWND, HDC, int, int);
int  CzyNowyRekord(POZYCJA*, POZ_TRUD, TRYB, unsigned int);
void DodajRekord(POZYCJA*, POZ_TRUD, TRYB, int, char*, unsigned int);
void ZapiszListe(POZYCJA*);
bool TworzListe();

////////////////////////////////Implementacja///////////////////////////////////
POZYCJA* PobierzDane() {
    FILE* pFin;
    POZYCJA* pPozycja;
    // probuje otworzyc plik z wynikami...
    if(!(pFin = fopen("data.bin", "rb"))) {
                // jesli plik np. zostal usuniety, tworze nowy zerujac wyniki...
                if(!TworzListe()) 
                          return NULL;
                // jesli plik sie utworzyl, ale jednak nie mozna z niego czytac
                // rezygnujemy :(
                if(!(pFin = fopen("data.bin", "rb"))) {
                          return NULL;
                }
    }
    pPozycja = (POZYCJA*)malloc(sizeof(POZYCJA) * MAX_LISTA);
    fread(pPozycja, sizeof(POZYCJA), MAX_LISTA, pFin);
    fclose(pFin);
    return pPozycja;
}
// Ponizsza funkca wyswietla wyniki z poszczegolnych trybow.
// Argument 'x' i 'y' opisyja polozenie tekstu, a pozostale dwa argumenty to
// rozmiar czcionki tekstu.
void OdczytajTryb(HDC hdc, POZYCJA* pLista, POZ_TRUD trudnosc, TRYB tryb, 
                  int x, int y, int xChar, int yChar) {
     POZYCJA* pTemp;
     char szBufor[25];
     int i;
     pTemp = pLista + (LEN_TRUD * trudnosc) + (LEN_TRYB * tryb);
     for(i = 0; i < LEN_TRYB; i++) {
           // wypisz nawe gracza
           TextOut(hdc, x, y + (i * yChar), szBufor,
                   wsprintf(szBufor, TEXT("%d. %s"), i + 1, (pTemp + i)->nazwa));
           // wypisz wynik tego gracza
           TextOut(hdc, x + (xChar * 20), y + (i * yChar), szBufor,
                   wsprintf(szBufor, TEXT("%05d"), (pTemp + i)->punkty));
     }
}
void OdczytajPozTrud(HDC hdc, POZYCJA* pLista, POZ_TRUD trudnosc) {
     char szPoziom[10];
     char szBufor[25];
     int i, xChar, yChar;
     TEXTMETRIC tm;
     RECT rc;
     char szNaglowek[] = "TABELA WYNIKÓW";
     char szPodkNaglowek[] = "________________";
     char* pPoziomy[] = {"ŁATWY", "ŚREDNI", "TRUDNY"};
     char* pTryby[] = {"25K", "50K", "95K"};
     GetTextMetrics(hdc, &tm);
     xChar = tm.tmAveCharWidth;
     yChar = tm.tmHeight + tm.tmExternalLeading;
     SetBkMode(hdc, TRANSPARENT);
     TextOut(hdc, 45 * xChar, yChar, szNaglowek, lstrlen(szNaglowek));
     TextOut(hdc, 45 * xChar, yChar, szPodkNaglowek, lstrlen(szPodkNaglowek));
     TextOut(hdc, 46 * xChar, 2 * yChar, szBufor, 
             wsprintf(szBufor, TEXT("POZIOM: %s"), pPoziomy[trudnosc]));
     for(i = 0; i < MAX_LISTA / LEN_TRUD; i++) {
           TextOut(hdc, 40 * xChar, (LEN_TRYB + i * 10) * yChar, szBufor,
                   wsprintf(szBufor, TEXT("TRYB %s"), pTryby[i]));
           OdczytajTryb(hdc, pLista, trudnosc, (TRYB)i, 41 * xChar,
                        (1 + LEN_TRYB + i * 10) * yChar, xChar, yChar);
     }
}
// poznizsza funkcja aktualizuje liste, poprzed wyodrebnienie odpowiednich
// regionow, a nastepnie ich odswiezenie
void AktualizujTabele(HWND hwnd, HDC hdc, int xChar, int yChar) {
     HRGN hRgnTemp[5];
     int i;
     hRgnTemp[0] = CreateRectRgn(55 * xChar, 2 * yChar, 63 * xChar, 3 * yChar);
     hRgnTemp[1] = CreateRectRgn(43 * xChar, 6 * yChar, 67 * xChar, 11 * yChar);
     hRgnTemp[2] = CreateRectRgn(43 * xChar, 16 * yChar, 67 * xChar, 21 * yChar);
     hRgnTemp[3] = CreateRectRgn(43 * xChar, 26 * yChar, 67 * xChar, 31 * yChar);
     hRgnTemp[4] = CreateRectRgn(0, 0, 1, 1);

     CombineRgn(hRgnTemp[4], hRgnTemp[0], hRgnTemp[1], RGN_OR);
     CombineRgn(hRgnTemp[0], hRgnTemp[4], hRgnTemp[2], RGN_OR);
     CombineRgn(hRgnTemp[4], hRgnTemp[0], hRgnTemp[3], RGN_OR);
                             
     InvalidateRgn(hwnd, hRgnTemp[4], TRUE);
     for(i = 0; i < 5; i++)
           DeleteObject(hRgnTemp[i]);
}
int  CzyNowyRekord(POZYCJA* pLista, POZ_TRUD trudnosc, TRYB tryb, unsigned int punkty) {
     POZYCJA* pTemp;
     int i;
     pTemp = pLista + (LEN_TRUD * trudnosc) + (LEN_TRYB * tryb);
     for(i = 0; i < LEN_TRYB; i++) {
           if((punkty <= (pTemp + i)->punkty) || (!(pTemp+i)->punkty))
                     return (i);
     }
     return (-1);
}
void DodajRekord(POZYCJA* pLista, POZ_TRUD trudnosc, TRYB tryb, int poz,
                 char* nazwa, unsigned int punkty) {
     POZYCJA* pTemp;
     int i;
     // wskazujemy na pierwszy elemenet w kategorii
     pTemp = pLista + (LEN_TRUD * trudnosc) + (LEN_TRYB * tryb);
     // przesun wszystkie wyniki mniejsze o jedna pozycje w dol
     for(i = LEN_TRYB - 1; i > poz; i--) {
           memcpy(pTemp + i, pTemp + (i - 1), sizeof(POZYCJA));
     }
     // zapisz nowy wynik
     strcpy((pTemp + i)->nazwa, nazwa);
     (pTemp + i)->punkty = punkty;
}
void ZapiszListe(POZYCJA* pLista) {
     FILE* pFout;
     pFout = fopen("data.bin", "wb");
     fwrite(pLista, sizeof(POZYCJA), MAX_LISTA, pFout);
     fclose(pFout);
}
bool TworzListe() {
      FILE* pFout;
      // probujemy utworzyc plik...
      if(!(pFout = fopen("data.bin", "wb"))) {
                 return false;
      }
      POZYCJA lista = {"Brak", 0};
      int i;
      // wypelniamy plik wartosciami poczatkowymi
      for(i = 0; i < MAX_LISTA; i++)
            fwrite(&lista, sizeof(POZYCJA), 1, pFout);
      fclose(pFout);
      return true;
}

#endif
