#ifndef __anime_h
#define __anime_h
#include <vector>
#include <map>
#include "date.h"
#include "window.h"

enum AnimeWatchingStatus {
	CURRENT,
	PLANNING,
	COMPLETED,
	DROPPED,
	PAUSED,
	REPEATING
};

enum AnimeAiringStatus {
	FINISHED,
	RELEASING,
	NOT_YET_RELEASED,
	CANCELLED,
	HIATUS
};

enum AnimeFormat {
	TV,
	TV_SHORT,
	MOVIE,
	SPECIAL,
	OVA,
	ONA,
	MUSIC,
	MANGA,
	NOVEL,
	ONE_SHOT
};

enum AnimeSeason {
	UNKNOWN,
	WINTER,
	SPRING,
	SUMMER,
	FALL
};

class Anime {
	public:
		Anime();
		Anime(const Anime& a);
		/* List-specific data */
		enum AnimeWatchingStatus status;
		int progress;
		int score;
		Date started;
		Date completed;
		int updated; /* this should be 64-bit */
		std::wstring notes;

		/* Useful information */
		int id;
		struct {
			std::wstring romaji;
			std::wstring english;
			std::wstring native;
		} title;
		int episodes;
		enum AnimeAiringStatus airing;
		Date air_date;
		std::vector<std::string> genres;
		std::vector<std::string> producers;
		enum AnimeFormat type;
		enum AnimeSeason season;
		int audience_score;
		std::wstring synopsis;
		int duration;
};

/* This is a simple wrapper on a vector that provides 
   methods to make it easier to search the list. */
class AnimeList {
	public:
		AnimeList();
		AnimeList(const AnimeList& l);
		~AnimeList();
		void Add(Anime& anime);
		void Insert(size_t pos, Anime& anime);
		void Delete(size_t index);
		void Clear();
		std::vector<Anime>::iterator begin() noexcept;
		std::vector<Anime>::iterator end() noexcept;
		std::vector<Anime>::const_iterator cbegin() noexcept;
		std::vector<Anime>::const_iterator cend() noexcept;
		size_t Size() const;
		Anime* AnimeById(int id);
		int GetAnimeIndex(Anime& anime) const;
		bool AnimeInList(int id);
		Anime& operator[](size_t index);
		const Anime& operator[](size_t index) const;
		std::wstring name;

	private:
		std::vector<Anime> anime_list;
		std::map<int, Anime*> anime_id_to_anime;
};

class AnimeListWidgetModel : public QAbstractListModel {
	Q_OBJECT
	public:
		enum columns {
			AL_TITLE,
			AL_PROGRESS,
			AL_SCORE,
			AL_AVG_SCORE,
			AL_TYPE,
			AL_SEASON,
			AL_STARTED,
			AL_COMPLETED,
			AL_UPDATED,
			AL_NOTES,
			
			NB_COLUMNS
		};

		AnimeListWidgetModel(QWidget* parent, AnimeList* alist);
		~AnimeListWidgetModel() override = default;
		//QVariant headerData(const int section, const Qt::Orientation orientation, const int role) const;
		int rowCount(const QModelIndex& parent = QModelIndex()) const;
		int columnCount(const QModelIndex& parent = QModelIndex()) const;
		QVariant data(const QModelIndex& index, int role) const;
		QVariant headerData(const int section, const Qt::Orientation orientation, const int role) const;
		Anime* GetAnimeFromIndex(const QModelIndex& index);
		void UpdateAnime(Anime& anime);

	private:
		//void AddAnime(AnimeList& list);
		AnimeList& list;
};

class AnimeListWidget : public QTreeView {
	Q_OBJECT
	public:
		AnimeListWidget(QWidget* parent, AnimeList* alist);

	private slots:
		void DisplayColumnHeaderMenu();
		void DisplayListMenu();
		void ItemDoubleClicked();
		void SetColumnDefaults();
		int VisibleColumnsCount() const;

	private:
		AnimeListWidgetModel* model = nullptr;
};

class AnimeListPage : public QTabWidget {
	public:
		AnimeListPage(QWidget* parent = nullptr);
		void SyncAnimeList();
		void FreeAnimeList();
		int GetTotalAnimeAmount();
		int GetTotalEpisodeAmount();
		int GetTotalWatchedAmount();
		int GetTotalPlannedAmount();
		double GetAverageScore();
		double GetScoreDeviation();

	private:
		std::vector<AnimeList> anime_lists;
};

extern std::map<enum AnimeSeason, std::string> AnimeSeasonToStringMap;
extern std::map<enum AnimeFormat, std::string> AnimeFormatToStringMap;
extern std::map<enum AnimeWatchingStatus, std::string> AnimeWatchingToStringMap;
extern std::map<enum AnimeAiringStatus, std::string> AnimeAiringToStringMap;
#endif // __anime_h