//
// Készítette: Toldi Balázs Ádám
// Dátum:  2020. 04. 07.
//

#ifndef HF_NAPTAR_NAPTAR_H
#define HF_NAPTAR_NAPTAR_H
//! @author Toldi Balázs Ádám
#include <iostream>
#include <cstring>
#include <algorithm>
#include <fstream>

#include "Datum.h"

/*!
 * @brief A naptár osztály tárolja azoknak a napoknak a dátumát,amely napok foglaltak már.
 * Ha az osztály kap egy dátumot, akkor el kell tudnia dönteni,hogy az adott nap szabad-e.
 * Fontos, hogy egy dátum csak egyszer szerepelhet.
 * Ha egy adott dátumot egynél többször szeretnénk felvenni, a program hibát dob.
 */
class Naptar {
  //! Dinamikusan méretezett tömb. A konstruktorban jön létre és a destruktorban szűnik meg.
  Datum **napok;
  //! A tömb aktuális mérete
  size_t db;
public:
  class iterator;

  /*!
   * @brief A tömb aktuális mérete
   * @return @copybrief size()
   */
  size_t size() const;

  /*!
   * @brief Paraméter nélkül hívható konstruktor
   */
  Naptar();

  /*!
   * @brief Konstruktor első elemmel
   * @param n Az első elem
   */
  Naptar(Datum* n);

  Naptar(const char* filename);
  /*!
   * @brief Megnézi, hogy egy adott dátum foglalt-e
   * @param nap A keresett dátum
   * @return Logikai változó az alapján, hogy foglalt-e
   */
  bool foglalt(const Datum nap);

  /*!
   * @copybrief foglalt()
   * @param ev @copybrief Datum.ev
   * @param honap @copybrief Datum.honap
   * @param nap @copybrief Datum.nap
   * @return Logikai változó az alapján, hogy foglalt-e
   */
  bool foglalt(int ev, int honap, int nap);

  /*!
   * @brief Kivesz egy Datum osztályt a tömbből
   * @param nap A Datum osztály, amit el szeretnénk távolítani
   * @note Ha az elem nem található,akkor a tartalma változatlan marad (Viszont erőforrást igényel).
   */
  void felszabadit(const Datum &nap);

  /*!
   * @copybrief felszabadit()
   * @param ev @copybrief Datum.ev
   * @param honap @copybrief Datum.honap
   * @param nap @copybrief Datum.nap
   * @note Ha az elem nem található,akkor a tartalma változatlan marad (Viszont erőforrást igényel).
   */
  void felszabadit(int ev, int honap, int nap);

  /*!
   * @brief Kiüríti a tömböt.
   */
  void urit();

  /*!
   * @brief Hozzáad egy új elemet a listához.
   * @param n A hozzáadandó datum osztály
   * @warning Ha a dátum már foglalt, kivételt dob.
   */
  void hozzaad(Datum* n);

  /*!
   * @copybrief hozzaad()
   * @param ev @copybrief Datum.ev
   * @param honap  @copybrief Datum.honap
   * @param nap @copybrief Datum.nap
   * @warning Ha a dátum már foglalt, kivételt dob.
   */
  void hozzaad(int ev, int honap, int nap);
  /*!
   * @brief Kiirja a megadott évre tervezett eseményeket
   * @param ev Az év,amely eseményeit szeretnénk kiírni
   */
  void printTable(int ev,std::ostream& os=std::cout,char spacer='\t');
  /*!
   * @brief Kiirja a megadott hónapra tervezett eseményeket
   * @param ev Az év,amely eseményeit szeretnénk kiírni
   * @param honap A hónap,amely eseményeit szeretnénk kiírni
   */
  void printTable(int ev,int honap,std::ostream& os=std::cout,char spacer='\t');
  /*!
   * @brief A naptár tartalmát kimenti egy CSV fájlba
   * @param path A fájl elérési útvonala
   * @note A naptár osztály tartalmát kiírja egy CSV fájlba.
   * A CSV táblázat oszlopai pontosvesszővel( ; ),a sorai sortöréssel vannak elválasztva.
   */
  void exportCSV(const char* path);
  /*!
   * @brief Destruktor. Itt törlődik az összes elem.
   */
  virtual ~Naptar();

  /*!
   * @brief Bejáró kezdete
   * @return Bejáró kezdete
   */
  iterator begin();


  /*!
   * @brief Bejáró vége
   * @return Bejáró vége
   */
  iterator end();
   

  /*!
   * @brief Visszaadja az adott helyen lévő Datum \link Naptar.iterator iterátor\endlink-át
   * @param id Az adott tag sorszáma
   * @return Az adott helyen lévő Datum \link Naptar.iterator iterátor\endlink-át
   * @note Az események időrendi sorrendben vannak
   */
  iterator at(size_t id);
  /*!
   * @brief Érték adó operátor
   * @param np A lemásolandó Naptár objektum
   * @return A lemásolt objektum
   */
  Naptar&operator=(const Naptar& np);
  /*!
   * Másoló konstruktor
   * @param np A lemásolandó Naptár objektum
   */
  Naptar(Naptar& np);

  /*!
   * Tömb iteráló(bejáró)
   */
  class iterator {
    //! Mutató az aktuális elemre
    Datum **akt;
    //! Mutató a tömb végére
    Datum **veg;
  public:
    //! Paraméter nélkül hívható konstruktor
    iterator() : akt(nullptr), veg(nullptr) {};

    /*!
     * @param nptr Naptár osztály,amihez szeretnénk a bejárót
     * @param n Az elem sorszáma
     */
    explicit iterator(Naptar &nptr, int n = 0) : akt(nptr.napok + n), veg(nptr.napok + nptr.db) {};

    /*!
     * @brief Bejáró dereferálása
     * @return Az érték amire mutat
     */
    Datum& operator*() const;

    /*!
     * @brief iterator léptetése (preinkrementer)
     */
    iterator operator++();

    /*!
     * @brief iterator léptetése (postinkrementer)
     */
    iterator operator++(int i);

    Datum *operator->();

    /*!
     * Két iterátor megegyezését ellenőrzi
     * @param it Az iterátor amivel össze szeretnénk hasonlítani a jelenlegit
     * @return Egyezést jelző logikai érték
     */
    bool operator==(const iterator &it);

    /*!
     * Az operator==() függvény negáltja
     * @param it Az iterátor amivel össze szeretnénk hasonlítani a jelenlegit
     * @return Egyenlőtlenséget jelző logikai érték
     */
    bool operator!=(const iterator &it);

    /*!
     * Két iterátor "távolságát" adja meg
     * @param it Az iterátor amivel össze szeretnénk hasonlítani a jelenlegit
     * @return Vissza adja, hogy mennyi adat van a két iterátor között
     */
    int operator-(const iterator &it);

  };
};

std::ostream &operator<<(std::ostream &os, Naptar &np);

#endif //HF_NAPTAR_NAPTAR_H
