#pragma once

#include <MSFS\Legacy\gauges.h>

#include <dirent.h>

#include "rapidjson/document.h"

#include "Base64.hpp"
#include "Utils.hpp"

#include "Constants.h"

namespace khofmann
{
	/// <summary>
	/// Read a file and return BASE64 encoded file contents
	/// </summary>
	/// <param name="path">Path of File</param>
	/// <param name="alloc">Allocator</param>
	/// <returns>BASE64 encoded file contents</returns>
	static rapidjson::Value readFile(const char* path, rapidjson::Document::AllocatorType& alloc)
	{
		FILE* file = fopen(path, "r");
		if (file) {
			fseek(file, 0, SEEK_END);
			long fsize = ftell(file);
			fseek(file, 0, SEEK_SET);

			char* string = (char*)calloc(sizeof(char), fsize + 1);
			fread(string, fsize, 1, file);
			fclose(file);

			return rapidjson::Value(macaron::Base64::Encode(string, fsize).c_str(), alloc);
		}

		return rapidjson::Value("", alloc);
	}

	/// <summary>
	/// Enumerate a directory and return list of directories.
	/// Return tumbnail as BASE64 and page count if present.
	/// </summary>
	/// <param name="path">Path of directory</param>
	/// <param name="alloc">Allocator</param>
	/// <returns>List of Files</returns>
	static rapidjson::Value enumerateDir(const char* path, rapidjson::Document::AllocatorType& alloc)
	{
		rapidjson::Value files;
		files.SetArray();

		int count = 0;

		DIR* d;
		struct dirent* dir;
		d = opendir(path);
		if (d)
		{
			while ((dir = readdir(d)) != NULL)
			{
				if (strcmp(dir->d_name, ".") && strcmp(dir->d_name, ".."))
				{
					std::string dirPath(path);
					dirPath += dir->d_name;
					std::string thumb(dirPath);
					thumb += "/thumb.png";
					FILE* check = fopen(thumb.c_str(), "r");
					if (check)
					{
						fclose(check);
						DIR* f;
						struct dirent* file;
						f = opendir(dirPath.c_str());
						if (f)
						{
							log(stdout, "Found file %s\n", dir->d_name);
							while ((file = readdir(f)) != NULL)
							{
								if (file->d_type == DT_REG)
								{
									count++;
								}
							}
							rapidjson::Value entry;
							entry.SetObject();
							entry.AddMember("name", rapidjson::Value(dir->d_name, alloc).Move(), alloc);
							entry.AddMember("pages", count - 1, alloc);
							entry.AddMember("thumb", readFile(thumb.c_str(), alloc).Move(), alloc);
							entry.AddMember("type", "file", alloc);
							files.PushBack(entry.Move(), alloc);
						}
						closedir(f);
					}
					else
					{
						log(stdout, "Found directory %s\n", dir->d_name);

						rapidjson::Value entry;
						entry.SetObject();
						entry.AddMember("name", rapidjson::Value(dir->d_name, alloc).Move(), alloc);
						entry.AddMember("type", "directory", alloc);
						files.PushBack(entry.Move(), alloc);
					}
				}
			}
		}
		closedir(d);

		return files;
	}
}