#if defined __custom_achievements_included
	#endinput
#endif

#define __custom_achievements_included

/**
 * Controls type of achievement.  Intended to be used when displaying the achievements in some
 * fashion (e.g., on a webpage).
 */
enum AchievementStyle {
	AchievementStyle_Undefined = 0, // Style is undefined (may need to be custom-made).
	AchievementStyle_Single, // Either it's achieved or it isn't; no renderable progress.
	AchievementStyle_Progress, // Requires a progress bar.
};

/**
 * Called when achievement metadata is fetched for an account.  If the account has no metadata
 * for the specified achievement, an empty string is returned.
 * 
 * There is no defined metadata format other than it being a string; the plugin is free to store
 * any relevant persistent information pertaining to that achievement for an account, if any.
 */
typedef AchievementMetadataCallback = function void(CustomAchievement achievement,
		const char[] metadata, any data);

methodmap CustomAchievement {
	/**
	 * Instantiates a custom achievement with the specified internal name, returning an
	 * identifier.
	 */
	public native CustomAchievement(const char[] internalName, AchievementStyle style);
	
	/**
	 * Flags the achievement as completed for this client.  If the achievement hasn't been
	 * awarded to the client before, `notify` is true, and the player is in the server,
	 * `OnCustomAchievementAwarded` is fired.
	 */
	public native void AwardToAccountID(int steamid3, bool notify = true);
	
	/**
	 * Flags the achievement as completed for this client.
	 */
	public void Award(int client, bool notify = true) {
		if (IsClientAuthorized(client)) {
			this.AwardToAccountID(GetSteamAccountID(client), notify);
		}
	}
	
	/**
	 * Performs a threaded query to get the metadata for this achievement for the specified
	 * Steam account.
	 */
	public native void FetchMetadataByAccountID(int steamid3,
			AchievementMetadataCallback callback, any data);
	
	/**
	 * Performs a threaded query to get the metadata for this achievement for the specified
	 * user.
	 * 
	 * (You'll probably want to pass the client in under the `data` argument in some way.)
	 */
	public void FetchMetadata(int client, AchievementMetadataCallback callback,
			any data) {
		if (IsClientAuthorized(client)) {
			this.FetchMetadataByAccountID(GetSteamAccountID(client), callback, data);
		}
	}
	
	/**
	 * Store the account-specific metadata for this achievement.
	 */
	public native bool StoreMetadataByAccountID(int steamid3, const char[] metadata);
	
	/**
	 * Performs a fast query to store the metadata for this achievement for the specified
	 * client.
	 */
	public bool StoreMetadata(int client, const char[] metadata) {
		if (IsClientAuthorized(client)) {
			return this.StoreMetadataByAccountID(GetSteamAccountID(client), metadata);
		}
		return false;
	}
	
	/**
	 * Resets this achievement, removing stored metadata and removing the "achieved" state for
	 * the specified account.
	 * 
	 * There is no `CustomAchievement.Reset(int client)` by design as achievements are not meant
	 * to be reset so often.
	 */
	public native void ResetByAccountID(int steamid3);
}

/**
 * Called when an achievement is awarded to an in-game player.
 * 
 * TODO implement a function to test if achievement(s) were already awarded, to check if a
 * milestone is reached, or something.
 */
forward void OnCustomAchievementAwarded(int client, CustomAchievement achievement);

public SharedPlugin __pl_custom_achievements = {
	name = "custom-achievements",
	file = "custom_achievements.smx",
#if defined REQUIRE_PLUGIN
	required = 1,
#else
	required = 0,
#endif
};

#if !defined REQUIRE_PLUGIN
public __pl_custom_achievements_SetNTVOptional() {
	MarkNativeAsOptional("CustomAchievement.CustomAchievement");
	
	MarkNativeAsOptional("CustomAchievement.AwardToAccountID");
	MarkNativeAsOptional("CustomAchievement.Award");
	
	MarkNativeAsOptional("CustomAchievement.FetchMetadataByAccountID");
	MarkNativeAsOptional("CustomAchievement.FetchMetadata");
	
	MarkNativeAsOptional("CustomAchievement.StoreMetadataByAccountID");
	MarkNativeAsOptional("CustomAchievement.StoreMetadata");
	
	MarkNativeAsOptional("CustomAchievement.ResetByAccountID");
}
#endif