/******************************************************************************
*
* Copyright (C) 2005-2018  Brian Berlin
* 
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
* 
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
* GNU General Public License for more details.
* 
* You should have received a copy of the GNU General Public License
* along with this program.  If not, see <http://www.gnu.org/licenses/>
*
******************************************************************************
*
* FILENAME: katconfig.h
*
* DESCRIPTION:  This contains function and struct declartions for configuration 
*               functions
*
* AUTHORS:  bberlin
*
* CHANGE LOG
*
*  VER     DATE     CHANGED BY   DESCRIPTION OF CHANGE
* ------  --------  ----------   ------------------------------------
* 0.1     06/18/05  bberlin      Creation
* 0.2     03/09/06  bberlin      Added more configuration items and functions
* 0.2.2   03/15/06  bberlin      Added deadzone parameter to t_atari_stick
* 0.2.3   03/17/06  bberlin      Added sound_freq and sound_samples parameters
*                                  to t_config.
* 0.3.0   04/01/06  bberlin      Added sensitivity parameter to t_atari_stick
* 0.3.0   04/05/06  bberlin      Added simulate_analog parameter to 
*                                  t_atari_stick
* 0.4.0   05/21/06  bberlin      Added ui_keys parameter to configuration
* 0.4.0   06/04/06  bberlin      Added hires_artifacts parameter to configuration
* 0.8.0   11/25/17  bberlin      Added get_filename for use with db_if
* 0.9.0   10/20/18  bberlin      Changed to TOML and redesigned structs
******************************************************************************/
#ifndef config_h
#define config_h

#include "../core/media.h"
#include "../core/console.h"
#include "atari_ntsc.h"
#include "shader_bundle.h"
#include "toml.h"

#define STATE_LOAD_NONE 0
#define STATE_LOAD_FILE 10

#define MAX_CONTROLLER 4
#define MAX_KEYS 64
#define MAX_KEYPAD_KEYS 16
#define MAX_UI_STATES 9

#define KCFG_SAVE 1
#define KCFG_LOAD 2

/* These defines are used to mask which config params get written on one call */
#define KCFG_GENERAL_MACHINE  0x00001ULL
#define KCFG_GENERAL_THROTTLE 0x00002ULL
#define KCFG_GENERAL_BASIC    0x00004ULL
#define KCFG_GENERAL_STATE    0x00008ULL
#define KCFG_GENERAL_STTS_DIR 0x00010ULL
#define KCFG_GENERAL_ROM      0x00020ULL
#define KCFG_GENERAL_BASIC_EN 0x00040ULL
#define KCFG_GENERAL_SIOP_EN  0x00080ULL
#define KCFG_GENERAL_QK_STAT  0x00100ULL
#define KCFG_GENERAL_FST_USE  0x00200ULL
#define KCFG_GENERAL_EXIT     0x00400ULL
#define KCFG_MACHINE_BIOS     0x00800ULL
#define KCFG_MACHINE_RAM      0x01000ULL
#define KCFG_MACHINE_NAME     0x02000ULL
#define KCFG_MACHINE_BIOS_DIR 0x04000ULL
#define KCFG_MACHINE_ROM_DIR  0x08000ULL
#define KCFG_MACHINE_PROF_DIR 0x10000ULL
#define KCFG_MACHINE_TV_STD   0x20000ULL
#define KCFG_MACHINE_BIOS_TYP 0x40000ULL
#define KCFG_GENERAL_START_WT 0x80000ULL
#define KCFG_GENERAL_DL_URL   0x100000ULL
#define KCFG_GENERAL_BASIC_TYP 0x200000ULL
#define KCFG_MACHINE_JOY_H_CTR 0x400000ULL
#define KCFG_MACHINE_JOY_V_CTR 0x800000ULL
#define KCFG_MACHINE_JOY_H_LOW 0x1000000ULL
#define KCFG_MACHINE_JOY_H_HIGH 0x2000000ULL
#define KCFG_MACHINE_JOY_V_LOW 0x4000000ULL
#define KCFG_MACHINE_JOY_V_HIGH 0x8000000ULL
#define KCFG_MACHINE_TRK_H_CTR 0x10000000ULL
#define KCFG_MACHINE_TRK_V_CTR 0x20000000ULL
#define KCFG_MACHINE_TRK_DPOT_MIN 0x40000000ULL
#define KCFG_MACHINE_TRK_DPOT_MAX 0x80000000ULL

#define KCFG_MEDIA_TITLE      0x00001ULL
#define KCFG_MEDIA_FILE       0x00002ULL
#define KCFG_MEDIA_SHA1       0x00004ULL
#define KCFG_MEDIA_MD5        0x00008ULL
#define KCFG_MEDIA_CRC        0x00010ULL
#define KCFG_MEDIA_SIZE       0x00020ULL
#define KCFG_MEDIA_WRT_PROT   0x00040ULL
#define KCFG_MEDIA_COLLECTS   0x00080ULL
#define KCFG_MEDIA_MAPPING    0x00100ULL
#define KCFG_MEDIA_TYPE       0x00200ULL
#define KCFG_MEDIA_MACHINE    0x00400ULL

#define KCFG_VIDEO_PALETTE    0x00002ULL
#define KCFG_VIDEO_FULLSCREEN 0x00004ULL
#define KCFG_VIDEO_HEIGHT     0x00008ULL
#define KCFG_VIDEO_WIDTH      0x00010ULL
#define KCFG_VIDEO_WIDE       0x00020ULL
#define KCFG_VIDEO_NTSC       0x00040ULL
#define KCFG_VIDEO_FIXED_WIN  0x00080ULL
#define KCFG_VIDEO_VSYNC      0x00100ULL
#define KCFG_VIDEO_X          0x00200ULL
#define KCFG_VIDEO_Y          0x00400ULL
#define KCFG_VIDEO_SHADER     0x00800ULL
#define KCFG_VIDEO_HUE        0x01000ULL
#define KCFG_VIDEO_SATURATION 0x02000ULL
#define KCFG_VIDEO_CONTRAST   0x04000ULL
#define KCFG_VIDEO_BRIGHTNESS 0x08000ULL
#define KCFG_VIDEO_SHARPNESS  0x10000ULL
#define KCFG_VIDEO_BRST_PHASE 0x20000ULL
#define KCFG_VIDEO_HUE_WARP   0x40000ULL
#define KCFG_VIDEO_WINDOW_SCALING 0x80000ULL
#define KCFG_VIDEO_TEXTURE_SCALING 0x100000ULL
#define KCFG_VIDEO_RENDERER   0x200000ULL
#define KCFG_VIDEO_GUI_SCALE  0x400000ULL

#define KCFG_SND_EN           0x00001ULL
#define KCFG_SND_FREQ         0x00002ULL
#define KCFG_SND_SAMPLES      0x00004ULL
#define KCFG_SND_BUFFER       0x00008ULL
#define KCFG_SND_GAIN         0x00010ULL

#define KCFG_SND_GAIN_MAX     150
#define KCFG_SND_BUFFER_AUTO  0.0f
#define KCFG_SND_BUFFER_MIN   1.0f
#define KCFG_SND_BUFFER_MAX   5.0f
#define KCFG_SND_BUFFER_DEFAULT 2.0f
#define KCFG_SND_BUFFER_OPENSL_ES 4.0f

#define KCFG_INP_PLAY_MASK    0x00300ULL
#define KCFG_INP_KEYBRD_MSK   0x00400ULL
#define KCFG_INP_GEN_MASK     0x00800ULL

#define KCFG_INP_JOY_EN       0x0000000000000001ULL
#define KCFG_INP_JOY_SENS     0x0000000000000002ULL
#define KCFG_INP_JOY_DEAD     0x0000000000000004ULL
#define KCFG_INP_SIM_AN       0x0000000000000008ULL
#define KCFG_INP_DPAD_EN      0x0000000000000010ULL
#define KCFG_INP_DPAD_AN_EN   0x0000000000000020ULL
#define KCFG_INP_DPAD_AN_SPD  0x0000000000000040ULL
#define KCFG_INP_MOUSE_EN     0x0000000000000080ULL
#define KCFG_INP_MOUSE_SPD    0x0000000000000100ULL
#define KCFG_INP_KEYBD_EN     0x0000000000000200ULL
#define KCFG_INP_TYPE         0x0000000000000400ULL
#define KCFG_INP_JOY_LEFT     0x0000000000000800ULL
#define KCFG_INP_JOY_RIGHT    0x0000000000001000ULL
#define KCFG_INP_JOY_UP       0x0000000000002000ULL
#define KCFG_INP_JOY_DOWN     0x0000000000004000ULL
#define KCFG_INP_JOY_TOP      0x0000000000008000ULL
#define KCFG_INP_JOY_BTM      0x0000000000010000ULL
#define KCFG_INP_JOY_KEY_STT  0x0000000000020000ULL
#define KCFG_INP_JOY_KEY_PAU  0x0000000000040000ULL
#define KCFG_INP_JOY_KEY_RST  0x0000000000080000ULL
#define KCFG_INP_JOY_KEY_STR  0x0000000000100000ULL
#define KCFG_INP_JOY_KEY_PND  0x0000000000200000ULL
#define KCFG_INP_JOY_KEY_0    0x0000000000400000ULL
#define KCFG_INP_JOY_KEY_1    0x0000000000800000ULL
#define KCFG_INP_JOY_KEY_2    0x0000000001000000ULL
#define KCFG_INP_JOY_KEY_3    0x0000000002000000ULL
#define KCFG_INP_JOY_KEY_4    0x0000000004000000ULL
#define KCFG_INP_JOY_KEY_5    0x0000000008000000ULL
#define KCFG_INP_JOY_KEY_6    0x0000000010000000ULL
#define KCFG_INP_JOY_KEY_7    0x0000000020000000ULL
#define KCFG_INP_JOY_KEY_8    0x0000000040000000ULL
#define KCFG_INP_JOY_KEY_9    0x0000000080000000ULL
#define KCFG_INP_TRK_LEFT     0x0000000100000000ULL
#define KCFG_INP_TRK_RIGHT    0x0000000200000000ULL
#define KCFG_INP_TRK_UP       0x0000000400000000ULL
#define KCFG_INP_TRK_DOWN     0x0000000800000000ULL
#define KCFG_INP_PADD_1_LEFT  0x0000001000000000ULL
#define KCFG_INP_PADD_1_RIGHT 0x0000002000000000ULL
#define KCFG_INP_PADD_1_BUTN  0x0000004000000000ULL
#define KCFG_INP_PADD_2_LEFT  0x0000008000000000ULL
#define KCFG_INP_PADD_2_RIGHT 0x0000010000000000ULL
#define KCFG_INP_PADD_2_BUTN  0x0000020000000000ULL
#define KCFG_INP_KEY_SHIFT    0x0000040000000000ULL
#define KCFG_INP_KEY_CTRL     0x0000080000000000ULL
#define KCFG_INP_KEY_BREAK    0x0000100000000000ULL
#define KCFG_INP_KEY_START    0x0000200000000000ULL
#define KCFG_INP_KEY_SELECT   0x0000400000000000ULL
#define KCFG_INP_KEY_OPTION   0x0000800000000000ULL
#define KCFG_INP_KEY_RESET    0x0001000000000000ULL
#define KCFG_INP_JOY_GUID     0x0002000000000000ULL
#define KCFG_INP_JOY_SERIAL   0x0004000000000000ULL
#define KCFG_INP_MOUSE_OPT    0x0008000000000000ULL
#define KCFG_INP_AUTO_FIRE    0x0010000000000000ULL
#define KCFG_INP_AUTO_FIRE_SPD 0x0020000000000000ULL

#define KCFG_UI_EXIT          0x0000000000000001ULL
#define KCFG_UI_BACK          0x0000000000000002ULL
#define KCFG_UI_FULLSCREEN    0x0000000000000004ULL
#define KCFG_UI_SCREENSHOT    0x0000000000000008ULL
#define KCFG_UI_DEBUGGER      0x0000000000000010ULL
#define KCFG_UI_LOAD_1        0x0000000000000100ULL
#define KCFG_UI_LOAD_2        0x0000000000000200ULL
#define KCFG_UI_LOAD_3        0x0000000000000400ULL
#define KCFG_UI_LOAD_4        0x0000000000000800ULL
#define KCFG_UI_LOAD_5        0x0000000000001000ULL
#define KCFG_UI_LOAD_6        0x0000000000002000ULL
#define KCFG_UI_LOAD_7        0x0000000000004000ULL
#define KCFG_UI_LOAD_8        0x0000000000008000ULL
#define KCFG_UI_LOAD_9        0x0000000000010000ULL
#define KCFG_UI_SAVE_1        0x0000000000100000ULL
#define KCFG_UI_SAVE_2        0x0000000000200000ULL
#define KCFG_UI_SAVE_3        0x0000000000400000ULL
#define KCFG_UI_SAVE_4        0x0000000000800000ULL
#define KCFG_UI_SAVE_5        0x0000000001000000ULL
#define KCFG_UI_SAVE_6        0x0000000002000000ULL
#define KCFG_UI_SAVE_7        0x0000000004000000ULL
#define KCFG_UI_SAVE_8        0x0000000008000000ULL
#define KCFG_UI_SAVE_9        0x0000000010000000ULL

typedef enum {
    DEV_KEYBOARD,
    DEV_JOYSTICK,
    DEV_MOUSE,
    DEV_CONTROLLER,
    DEV_MAX
} e_dev_type;

typedef enum {
    PART_TYPE_HAT,
    PART_TYPE_AXIS,
    PART_TYPE_BALL,
    PART_TYPE_BUTTON,
    PART_TYPE_KEY,
    PART_TYPE_MAX
} e_part_type;

typedef enum {
    DIR_LEFT,
    DIR_RIGHT,
    DIR_UP,
    DIR_DOWN,
    MAX_DIR,
    DIR_PLUS,
    DIR_MINUS,
    DIR_PRESS,
    DIR_RELEASE
} e_direction;

typedef enum {
    CTRLR_TYPE_NONE,
    CTRLR_TYPE_JOYSTICK,
    CTRLR_TYPE_TRACKBALL,
    CTRLR_TYPE_PADDLES,
    CTRLR_TYPE_KEYPAD,
    CTRLR_TYPE_MAX
} e_ctrlr_type;

typedef enum {
    START_GUI_ROMS,
    START_GUI_BROWSER,
    START_GUI_LAST_ROM
} e_start_type;

typedef enum {
    WINDOW_SCALING_LETTERBOX = 0,
    WINDOW_SCALING_STRETCH   = 1,
    WINDOW_SCALING_FIT_WINDOW = 2
} e_window_scaling;

typedef enum {
    TEXTURE_SCALING_PIXELATED = 0,
    TEXTURE_SCALING_SMOOTH = 1
} e_texture_scaling;

typedef enum {
    MOUSE_OPTIMIZE_PADDLES = 0,
    MOUSE_OPTIMIZE_CURSOR  = 1
} e_mouse_optimize;

struct generic_node {
    char name[1024];
    unsigned long  value;
    unsigned long  data;
    struct generic_node *next;
};

struct collection {
    char *name;
    unsigned long value;
    struct collection *next;
};

typedef struct collection t_collection;

typedef struct {
    e_machine_type machine;
    int throttle;
    char *basic;
    char *basic_type;
    int basic_enable;
    char *state;
    int quick_state;
    char *rom;
    int rom_mapping;
    int sio_patch;
    int exit_status;
    int first_use;
    e_start_type start_with;
    char *states_dir;
    char *download_url;
    t_collection *collection;
} t_general;

typedef struct {
    int ram;
    int tv_standard;
    char *name;
    char *bios;
    char *bios_type;
    char *bios_dir;
    char *rom_dir;
    char *profiles_dir;
    int joystick_hpot_center;
    int joystick_vpot_center;
    int joystick_hpot_low;
    int joystick_hpot_high;
    int joystick_vpot_low;
    int joystick_vpot_high;
    int trackball_hpot_center;
    int trackball_vpot_center;
    int trackball_dpot_min;
    int trackball_dpot_max;
} t_machine;

typedef struct {
    int palette[256];
    char *palette_name;
    int fullscreen;
    int height;
    int width;
    int wide_playfield;
    int ntsc_artifacts;
    int fixed_window;
    int window_scaling;
    int texture_scaling;
    int x;
    int y;
    int vsync;
    char *shader;
    char *renderer_name;
    int gui_scale;
    atari_ntsc_setup_t ntsc_setup;
} t_video;

typedef struct {
    int enable;
    int frequency;
    int samples;
    float buffer_size;
    int gain;
} t_sound;

typedef struct {
    int index;
    char *name;
    char *guid;
} t_input_joysticks;

struct input_common {
    int enable;
    e_dev_type device[2];
    int device_num[2];
    e_part_type part_type[2];
    int part_num[2];
    e_direction direction[2];
    int combo;
    struct input_common *next;
};

typedef struct input_common t_input_common;

typedef struct {
    t_input_common left;
    t_input_common right;
    t_input_common button;
} t_paddle_input;

typedef struct {
    int joy_enable;
    int dpad_enable;
    int keyboard_enable;
    int mouse_enable;
    int mouse_speed;
    int auto_fire;
    int auto_fire_speed;
    int mouse_optimize;
    int joy_deadzone;
    int joy_sensitivity; 
    int analog_stick_acts_digital;
    int digdir_analog_enable;
    int digdir_analog_speed;
    int show_disabled;
    char joy_guid[48];
    char joy_serial[64];
    e_ctrlr_type type;
    t_input_common stick[MAX_DIR];
    t_input_common trackball[MAX_DIR];
    t_paddle_input paddles[2];
    t_input_common top_button;
    t_input_common bottom_button;
    t_input_common keypad[MAX_KEYPAD_KEYS];
} t_player_input;

typedef struct {
    t_player_input players[MAX_CONTROLLER];
    t_input_common keyboard[MAX_KEYS];
    t_input_common ctrl_key;
    t_input_common shift_key;
    t_input_common break_key;
    t_input_common start_key;
    t_input_common select_key;
    t_input_common option_key;
    t_input_common reset_key;
} t_game_input;

typedef struct {
    t_input_common exit;
    t_input_common back;
    t_input_common fullscreen;
    t_input_common screenshot;
    t_input_common debugger;
    t_input_common state_load[MAX_UI_STATES];
    t_input_common state_save[MAX_UI_STATES];
} t_ui_input;

struct joystick {
    char *name;
    int index;
    char guid[33];
};
typedef struct joystick t_joystick;

typedef struct {
    t_ui_input ui;
    t_game_input game;
} t_input;

typedef struct {
    t_general general;
    t_machine machine;
    t_sound sound;
    t_video video;
    t_input input;
    unsigned long long general_mask;
    unsigned long long sound_mask;
    unsigned long long video_mask;
    unsigned long long input_mask[MAX_CONTROLLER];
    unsigned long long keyboard_mask;
} t_config;

t_config * config_get_global_cfg ( void );
t_toml_node * config_get_global_table ( void );
t_toml_node * config_get_rom_table ( void );
t_toml_node * config_ensure_rom_table ( void );
char * config_get_filename ( void );
void config_init (  int argc, char *argv[] );
void config_exit ( void );
void config_check_arguments ( void );
int config_get_safe_video_mode ( void );
int config_update ( void );
void config_clear_masks();
void config_refresh_rom_source_masks(void);
void config_restore_loaded_media_context(void);
void config_save_os ( int os_type, const char *file );
const char * config_get_os_type_string ( int os_type );
int config_get_os_type_from_string ( const char *type );
const char * config_resolve_bios_tag ( const char *bios_type, int tv_standard );
void config_save_basic ( int basic_type, const char *file );
int config_load_basic_file ( t_toml_node *tbl );
const char * config_get_basic_type_string ( int basic_type );
int config_get_basic_type_from_string ( const char *type );
int config_get_exit_status ( void );
int config_set_exit_status ( void );
int config_get_first_use ( void );
char * config_get_os_file ( void );
int config_load_os_file ( t_toml_node *tbl );
void config_load_machine_settings ( t_toml_node *tbl );
void config_load_basic_settings ( t_toml_node *tbl );
void config_refresh_machine_settings ( void );
int config_delete_group ( t_config *p_config, char *node_name );
e_direction config_get_direction_from_string ( const char *string );
char * config_get_string_from_direction( int direction, char *string );
char * config_get_profiles_dir ( e_machine_type machine );
void config_load_directories_by_machine ( t_toml_node *tbl, e_machine_type m_type, 
    char **rom_dir, char **bios_dir );
void config_save_directories_by_machine ( t_toml_node *tbl, unsigned long long mask,
    e_machine_type m_type, char *rom_dir, char *bios_dir );
/* Flush a table to its file.  Most config_save_* helpers do this themselves;
 * the ones that only set keys (see config_save_directories_by_machine) leave it
 * to the caller so a batch of edits costs a single write. */
void config_write_file ( t_toml_node *tbl );
char * config_alloc_rom_browser_start_dir ( void );
void config_load_general ( t_toml_node *tbl );
void config_save_general ( t_toml_node *tbl, unsigned long long mask );
void config_load_video (t_toml_node *tbl, const char *tag );
void config_save_video ( t_toml_node *tbl, const char *tag,
        unsigned long long mask );
void config_load_shader_bundle_info ( t_toml_node *tbl, t_shader_bundle *bundle,
        int reset_defaults );
void config_shader_bundle_info ( t_toml_node *tbl, t_shader_bundle *bundle,
                                 int action );
int config_load_palette (t_toml_node * tbl, const char *name, int *palette );
void config_save_palette (t_toml_node * tbl, const char *name, int *palette );
int config_palette_exists (t_toml_node *tbl, const char *name);
int config_delete_palette (t_toml_node *tbl, const char *name);
void config_save_active_palette_name (t_toml_node *tbl, const char *tag,
                                      const char *name);
int config_fallback_active_palette_after_delete (t_toml_node *tbl,
                                                 const char *deleted_name);
int config_get_palette_names (t_toml_node *tbl, char **names, int max_names);
void config_load_sound (t_toml_node *tbl, const char *tag );
void config_save_sound ( t_toml_node *tbl, const char *tag, 
        unsigned long long mask );
void config_save_game_input (e_machine_type type, t_toml_node *tbl, 
        const char *tag, unsigned long long *mask, unsigned long long keymask );
void config_load_game_input (e_machine_type type, t_toml_node *tbl, 
        const char *tag );
void config_load_ui_input (t_toml_node *tbl );
void config_save_ui_input (t_toml_node *tbl, unsigned long long mask );
int config_load_media_settings ( unsigned int crc, t_media *p_media );
int config_save_media_settings ( unsigned int crc, t_media *p_media,
        unsigned long long mask );
void config_reset_media_custom_settings ( unsigned int crc );
void config_load_for_media ( unsigned int crc );
void config_load_debugger_window_pos ( const char *window_key, int *x, int *y, int *w, int *h );
void config_save_debugger_window_pos ( const char *window_key, int x, int y, int w, int h );
void config_load_filebrowser_size ( int *w, int *h );
void config_save_filebrowser_size ( int w, int h );
void config_load_debugger_breakpoints ( void );
void config_save_debugger_breakpoint ( int bp_type, int bp_value );
void config_delete_debugger_breakpoint ( int bp_type, int bp_value );
#endif
