#pragma once

#include <string>
#include <functional>
#include <map>
#include "olcPixelGameEngine.h"
#include "olcUTIL_DataFile.h"

class Crawler;
class ItemInfo;
class ItemProps;

typedef std::string IT;
typedef std::string ITCategory;

typedef std::function<bool(Crawler*,ItemProps)> ItemScript;

class Item{
	friend class Inventory;
private:
	uint32_t amt;
	ItemInfo*it;
public:
	Item();
	Item(uint32_t amt,IT item);
	uint32_t Amt();
	std::string Name();
	std::string Description();
	ITCategory Category();
	Decal*Decal();
	ItemScript&OnUseAction();
	bool IsBlank();
	static Item BLANK;
};

class Inventory{
	friend class ItemInfo;
public:
	static void AddItem(IT it,uint32_t amt=1);
	static uint32_t GetItemCount(IT it);
	static Item GetItem(IT it);
	//Auto-executes its use function and removes the amt specified from the inventory. Multiple amounts will cause the item to execute its useFunc multiple times.
	static void UseItem(IT it,uint32_t amt=1);
	static void RemoveItem(IT it,uint32_t amt=1);
	static std::vector<IT>&get(ITCategory itemCategory);

	static bool SwapItems(ITCategory itemCategory,uint32_t slot1,uint32_t slot2);
private:
	static void InsertIntoSortedInv(IT item);
	static bool ExecuteAction(IT item);
	static std::map<IT,Item>_inventory;
	static std::map<ITCategory,std::vector<IT>>sortedInv;
};

class ItemProps{
	friend class ItemInfo;
	utils::datafile*scriptProps; 
	utils::datafile*customProps; 
public:
	ItemProps(utils::datafile*scriptProps,utils::datafile*customProps);
	int GetIntProp(std::string prop);
	float GetFloatProp(std::string prop);
	std::string GetStringProp(std::string prop);
};

class ItemInfo{
	friend class Inventory;
	std::string name;
	std::string description;
	std::string category;
	Decal*img;
	//Returns true if the item can be used, false otherwise
	std::string useFunc="";
	//Custom properties for this specific item's script.
	static utils::datafile NOPROPS;
	ItemProps customProps;

private:
	static void InitializeScripts();
public:
	static void InitializeItems();
	ItemInfo();
	std::string Name();
	std::string Description();
	ITCategory Category();
	Decal*Decal();
	ItemScript&OnUseAction();
	/*
		For the useFunc, return true if the item can be used, false otherwise.
	*/
};