#pragma once

#include <filesystem>
#include <map>
#include <string>
#include <vector>
#include "ini.h"
#include "resource.h"

/* Resources are cached.
 * A resource of same file with different
 * type, is considered a seperate resource.
 * 
 * Each resource needs to inherit from
 * resource, and have a constructor like this:
 * (resource_manager& rm, ini_category const* ini, std::string const& path, std::vector<uint8_t> const& data)
 */

struct resource_manager {
	resource_manager();

	void mount(std::string const& path, std::string const& mounting_point);
	template <typename T>
	T const* get(std::filesystem::path const& path);

private:
	std::vector<uint8_t> read(std::filesystem::path const& path);
	bool resource_exists(std::filesystem::path const& path);
	std::map<std::string, std::map<std::string, resource*>> _map;
};

template <typename T>
T const* resource_manager::get(std::filesystem::path const& path) {
	static_assert(std::is_base_of<resource, T>::value);
	

	if(!_map[typeid(T).name()].contains(path.string())) {
		ini const* ini = 0;
		if(path.filename() != "assets.ini") {
			std::filesystem::path ini_path = path;
			ini_path.replace_filename("assets.ini");
			if(resource_exists(ini_path)) {
				ini = get<::ini>(ini_path);
			}
		}
		ini_category const* cat = &ini_category::empty;
		if(ini)
			cat = ini->get_category(path.filename().string());
		_map[typeid(T).name()].emplace(path.string(), new T(*this, cat, path.string(), read(path)));
	}
	return static_cast<T const*>(_map[typeid(T).name()].at(path.string()));
}
