//=============================================================================
//
// Adventure Game Studio (AGS)
//
// Copyright (C) 1999-2011 Chris Jones and 2011-2026 various contributors
// The full list of copyright holders can be found in the Copyright.txt
// file, which is part of this source code distribution.
//
// The AGS source code is provided under the Artistic License 2.0.
// A copy of this license can be found in the file License.txt and at
// https://opensource.org/license/artistic-2-0/
//
//=============================================================================
//
// AGS Runtime header
//
//=============================================================================
#ifndef __AGS_EE_AC__GAME_H
#define __AGS_EE_AC__GAME_H

#include <memory>
#include "ac/runtime_defines.h"
#include "ac/dynobj/scriptviewframe.h"
#include "gfx/bitmap.h"
#include "main/game_file.h"
#include "util/string.h"

// Forward declaration
namespace AGS { namespace Common { class AssetManager; class Stream; } }
using namespace AGS; // FIXME later

#define RAGMODE_PRESERVEGLOBALINT 1
#define RAGMODE_LOADNOW 0x8000000  // just to make sure it's non-zero

// Game parameter constants for backward-compatibility functions
#define GP_SPRITEWIDTH   1
#define GP_SPRITEHEIGHT  2
#define GP_NUMLOOPS      3
#define GP_NUMFRAMES     4
#define GP_ISRUNNEXTLOOP 5
#define GP_FRAMESPEED    6
#define GP_FRAMEIMAGE    7
#define GP_FRAMESOUND    8
#define GP_NUMGUIS       9
#define GP_NUMOBJECTS    10
#define GP_NUMCHARACTERS 11
#define GP_NUMINVITEMS   12
#define GP_ISFRAMEFLIPPED 13

enum CutsceneSkipStyle
{
    kSkipSceneUndefined = 0,
    eSkipSceneEscOnly = 1,
    eSkipSceneAnyKey = 2,
    eSkipSceneMouse = 3,
    eSkipSceneKeyMouse = 4,
    eSkipSceneEscOrRMB = 5,
    eSkipSceneScriptOnly = 6
};

//=============================================================================
// Audio
//=============================================================================
#define VOL_CHANGEEXISTING   1678
#define VOL_SETFUTUREDEFAULT 1679
#define VOL_BOTH             1680

void Game_StopAudio(int audioType);
int  Game_IsAudioPlaying(int audioType);
void Game_SetAudioTypeSpeechVolumeDrop(int audioType, int volumeDrop);
void Game_SetAudioTypeVolume(int audioType, int volume, int changeType);

int Game_GetMODPattern();

//=============================================================================
// ---
//=============================================================================
int Game_GetDialogCount();

// Sets a default save directory, based on platform driver settings and user config
void SetDefaultSaveDirectory();
// Sets a new save directory within the save parent; copies "restart" slot if available
int Game_SetSaveGameDirectory(const char *newFolder);
const char* Game_GetSaveSlotDescription(int slnum);

const char* Game_GetGlobalStrings(int index);

// Various sort parameter validation.
ScriptFileSortStyle ValidateFileSort(const char *apiname, int file_sort);
ScriptSaveGameSortStyle ValidateSaveGameSort(const char *apiname, int save_sort);
ScriptSortDirection ValidateSortDirection(const char *apiname, int sort_dir);
// Save slot range validation; fixups min and max slots, returns if the resulting range is non-empty
bool ValidateSaveSlotRange(const char *api_name, int &min_slot, int &max_slot);

// View, loop, frame parameter assertions.
// WARNING: these functions assume that view is already in an internal 0-based range.
void AssertView(const char *apiname, const char *objname, int view);
void AssertViewHasLoops(const char *apiname, const char *objname, int view);
void AssertLoop(const char *apiname, const char *objname, int view, int loop);
void AssertFrame(const char *apiname, const char *objname, int view, int loop, int frame);

int Game_GetInventoryItemCount();
int Game_GetFontCount();
int Game_GetMouseCursorCount();
int Game_GetCharacterCount();
int Game_GetGUICount();
int Game_GetViewCount();
int Game_GetUseNativeCoordinates();
int Game_GetSpriteWidth(int spriteNum);
int Game_GetSpriteHeight(int spriteNum);
int Game_GetLoopCountForView(int viewNumber);
int Game_GetRunNextSettingForLoop(int viewNumber, int loopNumber);
int Game_GetFrameCountForLoop(int viewNumber, int loopNumber);
ScriptViewFrame* Game_GetViewFrame(int viewNumber, int loopNumber, int frame);
int Game_DoOnceOnly(const char *token);

int  Game_GetTextReadingSpeed();
void Game_SetTextReadingSpeed(int newTextSpeed);
int  Game_GetMinimumTextDisplayTimeMs();
void Game_SetMinimumTextDisplayTimeMs(int newTextMinTime);
int  Game_GetIgnoreUserInputAfterTextTimeoutMs();
void Game_SetIgnoreUserInputAfterTextTimeoutMs(int newValueMs);
const char *Game_GetFileName();
const char *Game_GetName();
void Game_SetName(const char *newName);

int Game_GetSkippingCutscene();
int Game_GetInSkippableCutscene();

int Game_GetColorFromRGB(int red, int grn, int blu);
const char* Game_InputBox(const char *msg);
const char* Game_GetLocationName(int x, int y);

const char* Game_GetGlobalMessages(int index);

int Game_GetSpeechFont();
int Game_GetNormalFont();

const char* Game_GetTranslationFilename();
int Game_ChangeTranslation(const char *newFilename);
const char* Game_GetSpeechVoxFilename();
bool Game_ChangeSpeechVox(const char *newFilename);

//=============================================================================

void set_debug_mode(bool on);
// Sets logical game FPS, telling how often the game should update
void set_game_speed(int new_fps);
// Gets strictly logical game FPS, regardless of whether this is real FPS right now or not.
float get_game_speed();
void setup_for_dialog();
void restore_after_dialog();
Common::String get_save_game_directory();
Common::String get_save_game_suffix();
void set_save_game_suffix(const Common::String &suffix);
// Returns full path to the save for the given slot number
Common::String get_save_game_path(int slotNum);
// Parses an input filepath and retrieves final path and respective save slot number, if possible.
// * if input contains an absolute filepath, then uses it directly;
// * if input contains a relative filename, then tests both cwd and game's save directory;
// * if input contains a number, then creates a path to the save file with that number
bool get_save_filepath_and_slot(const Common::String &input_savepath, Common::String &filepath, int &slot);
// Try calling built-in restore game dialog;
// NOTE: this is a script command; may be aborted according to the game & room settings
void restore_game_dialog();
void restore_game_dialog2(int min_slot, int max_slot);
// Unconditionally display a built-in restore game dialog
bool do_restore_game_dialog(int min_slot, int max_slot);
// Try calling built-in save game dialog;
// NOTE: this is a script command; may be aborted according to the game & room settings
void save_game_dialog();
void save_game_dialog2(int min_slot, int max_slot);
// Unconditionally display a built-in save game dialog
bool do_save_game_dialog(int min_slot, int max_slot);
void free_do_once_tokens();
// Shuts down game's running state objects
void shutdown_game_state();
// Free all the memory associated with the game
void unload_game();
void save_game(int slotn, const Common::String &descript, std::unique_ptr<Common::Bitmap> &&image = nullptr);
std::unique_ptr<Common::Bitmap> create_game_screenshot(int width, int height, int layers);
bool read_savedgame_description(const Common::String &filename, Common::String &description);
std::unique_ptr<Common::Bitmap> read_savedgame_screenshot(const Common::String &filename);
// Tries to restore saved game and displays an error on failure; if the error occured
// too late, when the game data was already overwritten, shuts engine down.
bool try_restore_save(int slot, bool startup = false);
bool try_restore_save(const Common::String &path, int slot, bool startup = false);
void serialize_bitmap(const Common::Bitmap *thispic, Common::Stream *out);
Common::Bitmap *read_serialized_bitmap(Common::Stream *in);
void skip_serialized_bitmap(Common::Stream *in);
void prescan_save_slots(int dest_arr_handle, int min_slot, int max_slot, int file_sort, int sort_dir, int user_param);

bool is_in_cutscene();
CutsceneSkipStyle get_cutscene_skipstyle();
void start_skipping_cutscene ();
bool check_skip_cutscene_keypress(int kgn);
bool check_skip_cutscene_mclick(int mbut);
void initialize_skippable_cutscene();
void stop_fast_forwarding();

int __GetLocationType(int xxx,int yyy, int allowHotspot0);

// Called whenever game loses input focus
void display_switch_out();
// Called whenever game gets input focus
void display_switch_in();
// Called when the game loses input focus and must suspend
void display_switch_out_suspend();
// Called when the game gets input focus and should resume
void display_switch_in_resume();

void replace_tokens(const char*srcmes,char*destm, size_t maxlen);
const char *get_global_message (int msnum);
void get_message_text (int msnum, char *buffer, char giveErr = 1);

// Notifies the game objects that certain sprite was updated.
// This make them update their render states, caches, and so on.
void game_sprite_updated(int sprnum, bool deleted = false);
// Precaches sprites for a view, within a selected range of loops.
void precache_view(int view, int first_loop = 0, int last_loop = INT32_MAX, bool with_sounds = false);

// Global AssetManager instance.
extern std::unique_ptr<AGS::Common::AssetManager> AssetMgr;

// An internal state id, telling how the new room was entered.
// This defines which events to run after room was loaded.
enum EnterNewRoomState
{
    kEnterRoom_None = 0,
    kEnterRoom_Normal = 1, // changed to room and finished fade-in
    kEnterRoom_FirstTime = 2, // same as normal, but this is first time this room is visited
    kEnterRoom_RestoredSave = 3, // loaded a room after restoring a save
};

extern EnterNewRoomState in_new_room;
extern int new_room_pos;
extern int new_room_x, new_room_y, new_room_loop;
extern bool new_room_placeonwalkable;
extern int displayed_room;
extern int frames_per_second; // fixed game fps, set by script
extern unsigned int loopcounter;
extern void set_loop_counter(unsigned int new_counter);
extern int game_paused;

#endif // __AGS_EE_AC__GAME_H
