#pragma once

#include <stdint.h>

#if defined(_WIN32)
#define ZGN_PLUGIN_CALL __cdecl
#if defined(ZGN_PLUGIN_EXPORTS)
#define ZGN_PLUGIN_EXPORT __declspec(dllexport)
#else
#define ZGN_PLUGIN_EXPORT __declspec(dllimport)
#endif
#else
#define ZGN_PLUGIN_CALL
#define ZGN_PLUGIN_EXPORT
#endif

#ifdef __cplusplus
extern "C" {
#endif

#define ZGN_PLUGIN_ABI_VERSION 12u

typedef struct ZgnVector3
{
	float x;
	float y;
	float z;
} ZgnVector3;

typedef struct ZgnPluginInfo
{
	const char* name;
	const char* author;
	const char* version;
	const char* description;
	uint32_t min_host_abi_version;
} ZgnPluginInfo;

typedef enum ZgnConfirmDialogResult
{
	ZGN_CONFIRM_DIALOG_RESULT_CONFIRM = 1,
	ZGN_CONFIRM_DIALOG_RESULT_CANCEL = 2,
	ZGN_CONFIRM_DIALOG_RESULT_CLOSE = 3,
	ZGN_CONFIRM_DIALOG_RESULT_BACKGROUND = 4,
	ZGN_CONFIRM_DIALOG_RESULT_FAULTED = 5
} ZgnConfirmDialogResult;

typedef struct ZgnWorldMonsterInfo
{
	void* entity;
	void* npc_component;
	void* map_npc_def;
	uint32_t runtime_id;
	uint32_t server_entity_id;
	uint32_t group_id;
	uint32_t group_entity_id;
	uint32_t npc_id;
	uint32_t stage_id;
	int32_t stage_type;
	int32_t is_loaded;
	int32_t is_on_stage;
	int32_t is_visible;
	int32_t is_monster;
	int32_t is_danger_monster;
	int32_t alive_state;
	int32_t status;
	int32_t map_npc_type;
	int32_t purpose_type;
	int32_t camp_id;
	uint32_t mapping_info_id;
	uint32_t nearest_teleport_mapping_info_id;
	float alert_value;
	float alert_value_normalized;
	float warning_percent;
	float combat_power;
	ZgnVector3 position;
	ZgnVector3 config_position;
} ZgnWorldMonsterInfo;

typedef struct ZgnPlayerStateInfo
{
	int32_t has_local_player;
	int32_t is_interactive_world_ready;
	int32_t is_in_battle;
	int32_t has_battle_info;
	int32_t game_mode_type;
	uint32_t current_battle_id;
	int32_t is_in_performance;
	int32_t is_performance_replaying;
} ZgnPlayerStateInfo;

typedef struct ZgnInteractionButtonInfo
{
	uint32_t host_runtime_id;
	int32_t enable;
	int32_t show_priority;
} ZgnInteractionButtonInfo;

typedef struct ZgnTreasureChestInfo
{
	void* entity;
	void* prop_component;
	void* map_prop_def;
	uint32_t runtime_id;
	uint32_t server_entity_id;
	uint32_t group_id;
	uint32_t group_entity_id;
	uint32_t prop_server_entity_id;
	uint32_t interaction_runtime_id;
	uint32_t map_group_id;
	uint32_t map_instance_id;
	uint32_t map_server_entity_id;
	uint32_t prop_id;
	uint32_t chest_id;
	uint32_t mapping_info_id;
	int32_t prop_type;
	int32_t prop_state;
	int32_t is_loaded;
	int32_t is_on_stage;
	int32_t is_visible;
	int32_t is_opened;
	ZgnVector3 position;
	ZgnVector3 config_position;
	char name[128];
	char prop_name[128];
	char map_name[128];
	char icon_path[128];
} ZgnTreasureChestInfo;

/* Deprecated: retained only for ABI 6 binary compatibility. */
typedef enum ZgnTextEntryDialogResult
{
	ZGN_TEXT_ENTRY_DIALOG_RESULT_CONFIRM = 1,
	ZGN_TEXT_ENTRY_DIALOG_RESULT_CLOSE = 2,
	ZGN_TEXT_ENTRY_DIALOG_RESULT_FAULTED = 3,
	ZGN_TEXT_ENTRY_DIALOG_RESULT_UNAVAILABLE = 4
} ZgnTextEntryDialogResult;

typedef struct ZgnHostApi
{
	uint32_t abi_version;
	const char* host_name;

	void (ZGN_PLUGIN_CALL* log)(const char* plugin_name, const char* message);
	const char* (ZGN_PLUGIN_CALL* get_resource_root)(void);
	const char* (ZGN_PLUGIN_CALL* get_log_directory)(void);
	const char* (ZGN_PLUGIN_CALL* get_plugin_directory)(void);

	void* (ZGN_PLUGIN_CALL* create_system_string_utf8)(const char* utf8);
	int32_t (ZGN_PLUGIN_CALL* get_unity_object_name_utf8)(void* object, char* buffer, uint32_t buffer_size);

	void* (ZGN_PLUGIN_CALL* get_main_camera)(void);
	void* (ZGN_PLUGIN_CALL* get_ui_camera)(void);
	void* (ZGN_PLUGIN_CALL* get_local_player)(void);
	int32_t (ZGN_PLUGIN_CALL* is_interactive_world_ready)(void);

	int32_t (ZGN_PLUGIN_CALL* get_local_player_position)(ZgnVector3* out_position);
	int32_t (ZGN_PLUGIN_CALL* set_local_player_position)(ZgnVector3 position);
	int32_t (ZGN_PLUGIN_CALL* get_transform_position)(void* transform, ZgnVector3* out_position);
	int32_t (ZGN_PLUGIN_CALL* set_transform_position)(void* transform, ZgnVector3 position);

	int32_t (ZGN_PLUGIN_CALL* show_hint_utf8)(const char* message);
	int32_t (ZGN_PLUGIN_CALL* validate_object)(void* object, const char* namespaze, const char* class_name, const char* source);

	int32_t (ZGN_PLUGIN_CALL* ui_begin_window_utf8)(const char* title, int32_t* open, float default_width, float default_height);
	void (ZGN_PLUGIN_CALL* ui_end_window)(void);
	void (ZGN_PLUGIN_CALL* ui_text_utf8)(const char* text);
	int32_t (ZGN_PLUGIN_CALL* ui_button_utf8)(const char* label, float width, float height);
	void (ZGN_PLUGIN_CALL* ui_same_line)(void);
	int32_t (ZGN_PLUGIN_CALL* ui_input_text_utf8)(const char* label, char* buffer, uint32_t buffer_size, float width, float height);

	uintptr_t game_assembly_base;
	uintptr_t il2cpp_module_base;
	void* (ZGN_PLUGIN_CALL* il2cpp_class_from_type_definition_index)(uint32_t type_definition_index);
	int32_t (ZGN_PLUGIN_CALL* show_sdk_code_dialog)(int32_t retcode);
	int32_t (ZGN_PLUGIN_CALL* show_ok_cancel_hint_utf8)(const char* message);
	int32_t (ZGN_PLUGIN_CALL* show_plugin_confirm_utf8)(const char* content, const char* ok_title, const char* cancel_title);
	int32_t (ZGN_PLUGIN_CALL* show_joypad_confirm_utf8)(const char* content, const char* accept_title, const char* cancel_title);
	int32_t (ZGN_PLUGIN_CALL* trigger_local_player_attack)(void);
	int32_t (ZGN_PLUGIN_CALL* trigger_local_player_maze_skill)(void);
	int32_t (ZGN_PLUGIN_CALL* show_custom_ok_cancel_hint_utf8)(const char* content, const char* title, const char* ok_title, const char* cancel_title);
	int32_t (ZGN_PLUGIN_CALL* get_local_player_uid)(uint32_t* out_uid);
	int32_t (ZGN_PLUGIN_CALL* get_local_player_nickname_utf8)(char* buffer, uint32_t buffer_size);
	int32_t (ZGN_PLUGIN_CALL* show_custom_ok_cancel_hint_event_utf8)(const char* content, const char* title, const char* ok_title, const char* cancel_title);
	int32_t (ZGN_PLUGIN_CALL* consume_confirm_dialog_event)(int32_t* out_request_id, int32_t* out_result);
	/* Deprecated compatibility slots. Host no longer exposes this API and will keep them NULL. */
	int32_t (ZGN_PLUGIN_CALL* show_custom_text_entry_dialog_event_utf8)(const char* title, const char* content, const char* placeholder, const char* default_value, int32_t multiline, int32_t max_length);
	int32_t (ZGN_PLUGIN_CALL* consume_text_entry_dialog_event)(int32_t* out_request_id, int32_t* out_result, char* text_buffer, uint32_t text_buffer_size);
	int32_t (ZGN_PLUGIN_CALL* get_system_datetime_utf8)(char* buffer, uint32_t buffer_size);
	int32_t (ZGN_PLUGIN_CALL* quit_game)(void);
	int32_t (ZGN_PLUGIN_CALL* logout_to_login)(void);
	int32_t (ZGN_PLUGIN_CALL* open_url_in_default_browser_utf8)(const char* url);
	int32_t (ZGN_PLUGIN_CALL* get_player_state_info)(ZgnPlayerStateInfo* out_info);
	int32_t (ZGN_PLUGIN_CALL* can_local_player_interact_option)(void);
	int32_t (ZGN_PLUGIN_CALL* get_visible_interaction_button_count)(void);
	int32_t (ZGN_PLUGIN_CALL* get_visible_interaction_button_info)(int32_t index, ZgnInteractionButtonInfo* out_info);
	int32_t (ZGN_PLUGIN_CALL* get_visible_interaction_button_text_utf8)(uint32_t host_runtime_id, char* buffer, uint32_t buffer_size);
	int32_t (ZGN_PLUGIN_CALL* get_visible_interaction_button_name_utf8)(uint32_t host_runtime_id, char* buffer, uint32_t buffer_size);
	int32_t (ZGN_PLUGIN_CALL* get_visible_interaction_button_icon_utf8)(uint32_t host_runtime_id, char* buffer, uint32_t buffer_size);
	int32_t (ZGN_PLUGIN_CALL* trigger_visible_interaction_button)(uint32_t host_runtime_id);
	int32_t (ZGN_PLUGIN_CALL* get_loaded_world_monster_count)(void);
	int32_t (ZGN_PLUGIN_CALL* get_loaded_world_monster_info)(int32_t index, ZgnWorldMonsterInfo* out_info);
	int32_t (ZGN_PLUGIN_CALL* get_nearest_world_monster_info)(ZgnWorldMonsterInfo* out_info);
	int32_t (ZGN_PLUGIN_CALL* get_world_monster_unique_name_utf8)(void* map_npc_def, char* buffer, uint32_t buffer_size);
	int32_t (ZGN_PLUGIN_CALL* get_loaded_treasure_chest_count)(void);
	int32_t (ZGN_PLUGIN_CALL* get_loaded_treasure_chest_info)(int32_t index, ZgnTreasureChestInfo* out_info);
	int32_t (ZGN_PLUGIN_CALL* get_nearest_treasure_chest_info)(ZgnTreasureChestInfo* out_info);
	int32_t (ZGN_PLUGIN_CALL* get_treasure_chest_text_name_utf8)(void* prop_component, char* buffer, uint32_t buffer_size);
	int32_t (ZGN_PLUGIN_CALL* get_http_auth_machine_code_utf8)(char* buffer, uint32_t buffer_size);
	int32_t (ZGN_PLUGIN_CALL* authorize_http_port_utf8)(const char* plugin_name, const char* auth_key, const char* bind_address, uint16_t port);
} ZgnHostApi;

typedef uint32_t (ZGN_PLUGIN_CALL* ZgnPluginGetAbiVersionFn)(void);
typedef const ZgnPluginInfo* (ZGN_PLUGIN_CALL* ZgnPluginGetInfoFn)(void);
typedef int32_t (ZGN_PLUGIN_CALL* ZgnPluginOnLoadFn)(const ZgnHostApi* host_api);
typedef void (ZGN_PLUGIN_CALL* ZgnPluginOnUpdateFn)(void);
typedef void (ZGN_PLUGIN_CALL* ZgnPluginOnUnloadFn)(void);
typedef void (ZGN_PLUGIN_CALL* ZgnPluginOnMenuFn)(void);
typedef void (ZGN_PLUGIN_CALL* ZgnPluginOnOverlayFn)(void);

typedef int32_t (ZGN_PLUGIN_CALL* ZgnUiBeginWindowUtf8Fn)(const char* title, int32_t* open, float default_width, float default_height);
typedef void (ZGN_PLUGIN_CALL* ZgnUiEndWindowFn)(void);
typedef void (ZGN_PLUGIN_CALL* ZgnUiTextUtf8Fn)(const char* text);
typedef int32_t (ZGN_PLUGIN_CALL* ZgnUiButtonUtf8Fn)(const char* label, float width, float height);
typedef void (ZGN_PLUGIN_CALL* ZgnUiSameLineFn)(void);
typedef int32_t (ZGN_PLUGIN_CALL* ZgnUiInputTextUtf8Fn)(const char* label, char* buffer, uint32_t buffer_size, float width, float height);

static inline int32_t ZGN_PLUGIN_CALL ZgnShowCustomOkCancelHintUtf8(
	const ZgnHostApi* host_api,
	const char* title,
	const char* content,
	const char* cancel_title,
	const char* confirm_title)
{
	return (host_api && host_api->show_custom_ok_cancel_hint_utf8)
		? host_api->show_custom_ok_cancel_hint_utf8(content, title, confirm_title, cancel_title)
		: 0;
}

static inline int32_t ZGN_PLUGIN_CALL ZgnGetLocalPlayerUid(
	const ZgnHostApi* host_api,
	uint32_t* out_uid)
{
	return (host_api && host_api->get_local_player_uid)
		? host_api->get_local_player_uid(out_uid)
		: 0;
}

static inline int32_t ZGN_PLUGIN_CALL ZgnGetLocalPlayerNicknameUtf8(
	const ZgnHostApi* host_api,
	char* buffer,
	uint32_t buffer_size)
{
	return (host_api && host_api->get_local_player_nickname_utf8)
		? host_api->get_local_player_nickname_utf8(buffer, buffer_size)
		: 0;
}

static inline int32_t ZGN_PLUGIN_CALL ZgnShowCustomOkCancelHintEventUtf8(
	const ZgnHostApi* host_api,
	const char* title,
	const char* content,
	const char* cancel_title,
	const char* confirm_title)
{
	return (host_api && host_api->show_custom_ok_cancel_hint_event_utf8)
		? host_api->show_custom_ok_cancel_hint_event_utf8(content, title, confirm_title, cancel_title)
		: 0;
}

static inline int32_t ZGN_PLUGIN_CALL ZgnConsumeConfirmDialogEvent(
	const ZgnHostApi* host_api,
	int32_t* out_request_id,
	int32_t* out_result)
{
	return (host_api && host_api->consume_confirm_dialog_event)
		? host_api->consume_confirm_dialog_event(out_request_id, out_result)
		: 0;
}

static inline int32_t ZGN_PLUGIN_CALL ZgnGetSystemDateTimeUtf8(
	const ZgnHostApi* host_api,
	char* buffer,
	uint32_t buffer_size)
{
	return (host_api && host_api->get_system_datetime_utf8)
		? host_api->get_system_datetime_utf8(buffer, buffer_size)
		: 0;
}

static inline int32_t ZGN_PLUGIN_CALL ZgnQuitGame(
	const ZgnHostApi* host_api)
{
	return (host_api && host_api->quit_game)
		? host_api->quit_game()
		: 0;
}

static inline int32_t ZGN_PLUGIN_CALL ZgnLogoutToLogin(
	const ZgnHostApi* host_api)
{
	return (host_api && host_api->logout_to_login)
		? host_api->logout_to_login()
		: 0;
}

static inline int32_t ZGN_PLUGIN_CALL ZgnOpenUrlInDefaultBrowserUtf8(
	const ZgnHostApi* host_api,
	const char* url)
{
	return (host_api && host_api->open_url_in_default_browser_utf8)
		? host_api->open_url_in_default_browser_utf8(url)
		: 0;
}

static inline int32_t ZGN_PLUGIN_CALL ZgnGetPlayerStateInfo(
	const ZgnHostApi* host_api,
	ZgnPlayerStateInfo* out_info)
{
	return (host_api && host_api->get_player_state_info)
		? host_api->get_player_state_info(out_info)
		: 0;
}

static inline int32_t ZGN_PLUGIN_CALL ZgnGetLoadedWorldMonsterCount(
	const ZgnHostApi* host_api)
{
	return (host_api && host_api->get_loaded_world_monster_count)
		? host_api->get_loaded_world_monster_count()
		: 0;
}

static inline int32_t ZGN_PLUGIN_CALL ZgnCanLocalPlayerInteractOption(
	const ZgnHostApi* host_api)
{
	return (host_api && host_api->can_local_player_interact_option)
		? host_api->can_local_player_interact_option()
		: 0;
}

static inline int32_t ZGN_PLUGIN_CALL ZgnGetVisibleInteractionButtonCount(
	const ZgnHostApi* host_api)
{
	return (host_api && host_api->get_visible_interaction_button_count)
		? host_api->get_visible_interaction_button_count()
		: 0;
}

static inline int32_t ZGN_PLUGIN_CALL ZgnGetVisibleInteractionButtonInfo(
	const ZgnHostApi* host_api,
	int32_t index,
	ZgnInteractionButtonInfo* out_info)
{
	return (host_api && host_api->get_visible_interaction_button_info)
		? host_api->get_visible_interaction_button_info(index, out_info)
		: 0;
}

static inline int32_t ZGN_PLUGIN_CALL ZgnGetVisibleInteractionButtonTextUtf8(
	const ZgnHostApi* host_api,
	uint32_t host_runtime_id,
	char* buffer,
	uint32_t buffer_size)
{
	return (host_api && host_api->get_visible_interaction_button_text_utf8)
		? host_api->get_visible_interaction_button_text_utf8(host_runtime_id, buffer, buffer_size)
		: 0;
}

static inline int32_t ZGN_PLUGIN_CALL ZgnGetVisibleInteractionButtonNameUtf8(
	const ZgnHostApi* host_api,
	uint32_t host_runtime_id,
	char* buffer,
	uint32_t buffer_size)
{
	return (host_api && host_api->get_visible_interaction_button_name_utf8)
		? host_api->get_visible_interaction_button_name_utf8(host_runtime_id, buffer, buffer_size)
		: 0;
}

static inline int32_t ZGN_PLUGIN_CALL ZgnGetVisibleInteractionButtonIconUtf8(
	const ZgnHostApi* host_api,
	uint32_t host_runtime_id,
	char* buffer,
	uint32_t buffer_size)
{
	return (host_api && host_api->get_visible_interaction_button_icon_utf8)
		? host_api->get_visible_interaction_button_icon_utf8(host_runtime_id, buffer, buffer_size)
		: 0;
}

static inline int32_t ZGN_PLUGIN_CALL ZgnTriggerVisibleInteractionButton(
	const ZgnHostApi* host_api,
	uint32_t host_runtime_id)
{
	return (host_api && host_api->trigger_visible_interaction_button)
		? host_api->trigger_visible_interaction_button(host_runtime_id)
		: 0;
}

static inline int32_t ZGN_PLUGIN_CALL ZgnGetLoadedWorldMonsterInfo(
	const ZgnHostApi* host_api,
	int32_t index,
	ZgnWorldMonsterInfo* out_info)
{
	return (host_api && host_api->get_loaded_world_monster_info)
		? host_api->get_loaded_world_monster_info(index, out_info)
		: 0;
}

static inline int32_t ZGN_PLUGIN_CALL ZgnGetNearestWorldMonsterInfo(
	const ZgnHostApi* host_api,
	ZgnWorldMonsterInfo* out_info)
{
	return (host_api && host_api->get_nearest_world_monster_info)
		? host_api->get_nearest_world_monster_info(out_info)
		: 0;
}

static inline int32_t ZGN_PLUGIN_CALL ZgnGetWorldMonsterUniqueNameUtf8(
	const ZgnHostApi* host_api,
	void* map_npc_def,
	char* buffer,
	uint32_t buffer_size)
{
	return (host_api && host_api->get_world_monster_unique_name_utf8)
		? host_api->get_world_monster_unique_name_utf8(map_npc_def, buffer, buffer_size)
		: 0;
}

static inline int32_t ZGN_PLUGIN_CALL ZgnGetLoadedTreasureChestCount(
	const ZgnHostApi* host_api)
{
	return (host_api && host_api->get_loaded_treasure_chest_count)
		? host_api->get_loaded_treasure_chest_count()
		: 0;
}

static inline int32_t ZGN_PLUGIN_CALL ZgnGetLoadedTreasureChestInfo(
	const ZgnHostApi* host_api,
	int32_t index,
	ZgnTreasureChestInfo* out_info)
{
	return (host_api && host_api->get_loaded_treasure_chest_info)
		? host_api->get_loaded_treasure_chest_info(index, out_info)
		: 0;
}

static inline int32_t ZGN_PLUGIN_CALL ZgnGetNearestTreasureChestInfo(
	const ZgnHostApi* host_api,
	ZgnTreasureChestInfo* out_info)
{
	return (host_api && host_api->get_nearest_treasure_chest_info)
		? host_api->get_nearest_treasure_chest_info(out_info)
		: 0;
}

static inline int32_t ZGN_PLUGIN_CALL ZgnGetTreasureChestTextNameUtf8(
	const ZgnHostApi* host_api,
	void* prop_component,
	char* buffer,
	uint32_t buffer_size)
{
	return (host_api && host_api->get_treasure_chest_text_name_utf8)
		? host_api->get_treasure_chest_text_name_utf8(prop_component, buffer, buffer_size)
		: 0;
}

static inline int32_t ZGN_PLUGIN_CALL ZgnGetHttpAuthMachineCodeUtf8(
	const ZgnHostApi* host_api,
	char* buffer,
	uint32_t buffer_size)
{
	return (host_api && host_api->get_http_auth_machine_code_utf8)
		? host_api->get_http_auth_machine_code_utf8(buffer, buffer_size)
		: 0;
}

static inline int32_t ZGN_PLUGIN_CALL ZgnAuthorizeHttpPortUtf8(
	const ZgnHostApi* host_api,
	const char* plugin_name,
	const char* auth_key,
	const char* bind_address,
	uint16_t port)
{
	return (host_api && host_api->authorize_http_port_utf8)
		? host_api->authorize_http_port_utf8(plugin_name, auth_key, bind_address, port)
		: 0;
}

ZGN_PLUGIN_EXPORT uint32_t ZGN_PLUGIN_CALL ZgnPlugin_GetAbiVersion(void);
ZGN_PLUGIN_EXPORT const ZgnPluginInfo* ZGN_PLUGIN_CALL ZgnPlugin_GetInfo(void);
ZGN_PLUGIN_EXPORT int32_t ZGN_PLUGIN_CALL ZgnPlugin_OnLoad(const ZgnHostApi* host_api);
ZGN_PLUGIN_EXPORT void ZGN_PLUGIN_CALL ZgnPlugin_OnUpdate(void);
ZGN_PLUGIN_EXPORT void ZGN_PLUGIN_CALL ZgnPlugin_OnUnload(void);
ZGN_PLUGIN_EXPORT void ZGN_PLUGIN_CALL ZgnPlugin_OnMenu(void);
ZGN_PLUGIN_EXPORT void ZGN_PLUGIN_CALL ZgnPlugin_OnOverlay(void);

#ifdef __cplusplus
}
#endif
