/*__            ___                 ***************************************
/   \          /   \          Copyright (c) 1996-2020 Freeciv21 and Freeciv
\_   \        /  __/          contributors. This file is part of Freeciv21.
 _\   \      /  /__     Freeciv21 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.
     _/     /\                  You should have received  a copy of the GNU
    /o)  (o/\ \_                General Public License along with Freeciv21.
    \_____/ /                     If not, see https://www.gnu.org/licenses/.
      \____/        ********************************************************/
#pragma once

// common
#include "fc_types.h" // MAX_LEN_NAME

/* Update this capability string when ever there is changes to ai_type
 * structure below. When changing mandatory capability part, check that
 * there's enough reserved_xx pointers in the end of the structure for
 * taking to use without need to bump mandatory capability again. */
#define FC_AI_MOD_CAPSTR "+Freeciv-3.1-ai-module-2019.Feb.16"

// Timers for all AI activities. Define it to get statistics about the AI.
#ifdef FREECIV_DEBUG
#undef DEBUG_AITIMERS
#endif // FREECIV_DEBUG

struct Treaty;
struct player;
struct adv_choice;
struct city;
struct unit;
struct tile;
struct settlermap;
class PFPath;
struct section_file;
struct adv_data;

enum incident_type { INCIDENT_ACTION = 0, INCIDENT_WAR, INCIDENT_LAST };

struct ai_type {
  char name[MAX_LEN_NAME];

  void *pprivate;

  struct {
    // Called for every AI type when server quits.
    void (*module_close)();

    /* Called for every AI type when game starts. Game is not necessarily new
       one, it can also be an old game loaded from a savegame. */
    void (*game_start)();

    // Called for every AI type when game has ended.
    void (*game_free)();

    // Called for every AI type when map tiles are allocated.
    void (*map_alloc)();

    /* Called for every AI type when the game map is ready, either generated
     * or, in case of scenario, loaded. */
    void (*map_ready)();

    // Called for every AI type when map tiles are freed.
    void (*map_free)();

    // Called for every AI type when new player is added to game.
    void (*player_alloc)(struct player *pplayer);

    // Called for every AI type when player is freed from game.
    void (*player_free)(struct player *pplayer);

    // Called for every AI type for each player in game when game saved.
    void (*player_save)(struct player *pplayer, struct section_file *file,
                        int plrno);

    // Called for every AI type for each player in game when game loaded.
    void (*player_load)(struct player *pplayer,
                        const struct section_file *file, int plrno);

    /* Called for every AI type for each player in game when game saved,
     * with each other player as parameter.
     * In practice it's good to use player_save_relations when you
     * want to add entries to "player%d.ai%d", but player_iterate() inside
     * player_save is better otherwise. The difference is in how clean
     * structure the produced savegame will have. */
    void (*player_save_relations)(struct player *pplayer,
                                  struct player *other,
                                  struct section_file *file, int plrno);

    /* Called for every AI type for each player in game when game loaded,
     * with each other player as parameter. */
    void (*player_load_relations)(struct player *pplayer,
                                  struct player *other,
                                  const struct section_file *file,
                                  int plrno);

    // AI console.
    void (*player_console)(struct player *pplayer, const char *cmd);

    // Called for AI type that gains control of player.
    void (*gained_control)(struct player *pplayer);

    // Called for AI type that loses control of player.
    void (*lost_control)(struct player *pplayer);

    // Called for AI type of the player who gets split to two.
    void (*split_by_civil_war)(struct player *original,
                               struct player *created);

    // Called for AI type of the player who got created from the split.
    void (*created_by_civil_war)(struct player *original,
                                 struct player *created);

    /* Called for player AI type when player phase begins. This is in the
     * beginning of phase setup. See also first_activities. */
    void (*phase_begin)(struct player *pplayer, bool new_phase);

    // Called for player AI type when player phase ends.
    void (*phase_finished)(struct player *pplayer);

    /* Called for every AI type when new city is added to game. Called even
     * for virtual cities. */
    void (*city_alloc)(struct city *pcity);

    /* Called for every AI type when new city is removed from game. Called
     * even for virtual cities. */
    void (*city_free)(struct city *pcity);

    /* Called for every AI type when new city is added to game. Called for
     * real cities only. */
    void (*city_created)(struct city *pcity);

    /* Called for every AI type when new city is removed from game. Called
     * for real cities only. */
    void (*city_destroyed)(struct city *pcity);

    // Called for player AI type when player gains control of city.
    void (*city_got)(struct player *pplayer, struct city *pcity);

    // Called for player AI type when player loses control of city.
    void (*city_lost)(struct player *pplayer, struct city *pcity);

    // Called for every AI type for each city in game when game saved.
    void (*city_save)(struct section_file *file, const struct city *pcity,
                      const char *citystr);

    // Called for every AI type for each city in game when game loaded.
    void (*city_load)(const struct section_file *file, struct city *pcity,
                      const char *citystr);

    /* Called for player AI type when building advisor has chosen something
     * to be built in a city. This can override that decision. */
    void (*choose_building)(struct city *pcity, struct adv_choice *choice);

    /* Called for player AI when building advisor prepares to make decisions.
     */
    void (*build_adv_prepare)(struct player *pplayer, struct adv_data *adv);

    /* Called for every AI type when building advisor is first initialized
     * for the turn. */
    void (*build_adv_init)(struct player *pplayer);

    /* Called for player AI when building advisor should set wants for
     * buildings. Without this implemented in AI type building advisor does
     * not adjust wants at all. */
    void (*build_adv_adjust_want)(struct player *pplayer,
                                  struct city *wonder_city);

    // Called for player AI when evaluating governments.
    void (*gov_value)(struct player *pplayer, struct government *gov,
                      adv_want *val, bool *override);

    // Called for every AI type when unit ruleset has been loaded.
    void (*units_ruleset_init)();

    // Called for every AI type before unit ruleset gets reloaded.
    void (*units_ruleset_close)();

    /* Called for every AI type when new unit is added to game. Called even
     * for virtual units. */
    void (*unit_alloc)(struct unit *punit);

    /* Called for every AI type when unit is removed from game. Called even
     * for virtual units. */
    void (*unit_free)(struct unit *punit);

    /* Called for every AI type when new unit is added to game. Called for
     * real units only. */
    void (*unit_created)(struct unit *punit);

    /* Called for every AI type when unit is removed from game. Called for
     * real units only. */
    void (*unit_destroyed)(struct unit *punit);

    // Called for player AI type when player gains control of unit.
    void (*unit_got)(struct unit *punit);

    // Called for player AI type when unit changes type.
    void (*unit_transformed)(struct unit *punit,
                             const struct unit_type *old_type);

    // Called for player AI type when player loses control of unit.
    void (*unit_lost)(struct unit *punit);

    // Called for unit owner AI type for each unit when turn ends.
    void (*unit_turn_end)(struct unit *punit);

    // Called for unit owner AI type when advisors goto moves unit.
    void (*unit_move)(struct unit *punit, struct tile *ptile,
                      const PFPath &path, int step);

    // Called for all AI types when ever unit has moved.
    void (*unit_move_seen)(struct unit *punit);

    /* Called for unit owner AI type when new advisor task is set for unit.
     */
    void (*unit_task)(struct unit *punit, enum adv_unit_task task,
                      struct tile *ptile);

    // Called for every AI type for each unit in game when game saved.
    void (*unit_save)(struct section_file *file, const struct unit *punit,
                      const char *unitstr);

    // Called for every AI type for each unit in game when game loaded.
    void (*unit_load)(const struct section_file *file, struct unit *punit,
                      const char *unitstr);

    /* Called for player AI type when autosettlers have been handled for the
     * turn. */
    void (*settler_reset)(struct player *pplayer);

    // Called for player AI type when autosettlers should find new work.
    void (*settler_run)(struct player *pplayer, struct unit *punit,
                        struct settlermap *state);

    /* Called for player AI type for each autosettler still working.
       Cancelling current work there will result in settler_run() call. */
    void (*settler_cont)(struct player *pplayer, struct unit *punit,
                         struct settlermap *state);

    /* Called for player AI type when unit wants to autoexplore towards a
     * tile. */
    void (*want_to_explore)(struct unit *punit, struct tile *target,
                            enum override_bool *allow);

    /* Called for player AI type in the beginning of player phase.
     * Unlike with phase_begin, everything is set up for phase already. */
    void (*first_activities)(struct player *pplayer);

    /* Called for player AI when player phase is already active when AI gains
     * control. */
    void (*restart_phase)(struct player *pplayer);

    /* Called for player AI type in the beginning of player phase. Not for
     * barbarian players. */
    void (*diplomacy_actions)(struct player *pplayer);

    // Called for player AI type in the end of player phase.
    void (*last_activities)(struct player *pplayer);

    /* Called for player AI type when diplomatic treaty requires evaluation.
     */
    void (*treaty_evaluate)(struct player *pplayer, struct player *aplayer,
                            struct Treaty *ptreaty);

    /* Called for player AI type when diplomatic treaty has been accepted
     * by both parties. */
    void (*treaty_accepted)(struct player *pplayer, struct player *aplayer,
                            struct Treaty *ptreaty);

    /* Called for player AI type when first contact with another player has
     * been established. Note that when contact is between two AI players,
     * callback might be already called for the other party, so you can't
     * assume relations to be all-pristine when this gets called. */
    void (*first_contact)(struct player *pplayer, struct player *aplayer);

    /* Called for player AI type of the victim when someone does some
     * violation against him/her. */
    void (*incident)(enum incident_type type, enum casus_belli_range scope,
                     const struct action *paction, struct player *receiver,
                     struct player *violator, struct player *victim);

    /* Called for player AI type of city owner when logging requires city
     * debug information. */
    void (*log_fragment_city)(char *buffer, int buflength,
                              const struct city *pcity);

    /* Called for player AI type of unit owner when logging requires unit
     * debug information. */
    void (*log_fragment_unit)(char *buffer, int buflength,
                              const struct unit *punit);

    // Called for player AI type to decide if another player is dangerous.
    void (*consider_plr_dangerous)(struct player *plr1, struct player *plr2,
                                   enum override_bool *result);

    /* Called for player AI type to decide if it's dangerous for unit to
     * enter tile. */
    void (*consider_tile_dangerous)(struct tile *ptile, struct unit *punit,
                                    enum override_bool *result);

    /* Called for player AI to decide if city can be chosen to act as wonder
     * city for building advisor. */
    void (*consider_wonder_city)(struct city *pcity, bool *result);

    // Called for player AI type with short internval
    void (*refresh)(struct player *pplayer);

    // Called for every AI type when tile has changed
    void (*tile_info)(struct tile *ptile);

    /* Called for every AI type when certain kind of city change has taken
     * place. Currently this gets called when:
     *  - city changes owner.
     */
    void (*city_info)(struct city *pcity);

    /* Called for every AI type when certain kind of unit change has taken
     * place. Currently this gets called when:
     *  - unit updates & conversions
     */
    void (*unit_info)(struct unit *punit);

    /* These are here reserving space for future optional callbacks.
     * This way we don't need to change the mandatory capability of the AI
     * module interface when adding such callbacks, but existing modules just
     * have these set to nullptr. Optional capability should be set when
     * taking one of these to use, so that new modules know if the server is
     * going to call these or is it too old version to do so. When mandatory
     * capability then changes again, please add new reservations to
     * replace those taken to use. */
    void (*reserved_01)();
    void (*reserved_02)();
    void (*reserved_03)();
    void (*reserved_04)();
    void (*reserved_05)();
  } funcs;
};

struct ai_type *ai_type_alloc();
void ai_type_dealloc();
struct ai_type *get_ai_type(int id);
int ai_type_number(const struct ai_type *ai);
void init_ai(struct ai_type *ai);
int ai_type_get_count();
const char *ai_name(const struct ai_type *ai);

struct ai_type *ai_type_by_name(const char *search);
const char *ai_type_name_or_fallback(const char *orig_name);

#ifdef DEBUG_AITIMERS
void ai_timer_init(void);
void ai_timer_free(void);
void ai_timer_start(const struct ai_type *ai);
void ai_timer_stop(const struct ai_type *ai);
void ai_timer_player_start(const struct player *pplayer);
void ai_timer_player_stop(const struct player *pplayer);
#else
#define ai_timer_init(...) (void) 0
#define ai_timer_free(...) (void) 0
#define ai_timer_start(...) (void) 0
#define ai_timer_stop(...) (void) 0
#define ai_timer_player_start(...) (void) 0
#define ai_timer_player_stop(...) (void) 0
#endif // DEBUG_AITIMERS

#define ai_type_iterate(NAME_ai)                                            \
  do {                                                                      \
    int _aii_;                                                              \
    int _aitotal_ = ai_type_get_count();                                    \
    for (_aii_ = 0; _aii_ < _aitotal_; _aii_++) {                           \
      struct ai_type *NAME_ai = get_ai_type(_aii_);

#define ai_type_iterate_end                                                 \
  }                                                                         \
  }                                                                         \
  while (false)                                                             \
    ;

// FIXME: This should also check if player is ai controlled
#define CALL_PLR_AI_FUNC(_func, _player, ...)                               \
  do {                                                                      \
    struct player *_plr_ = _player; /* _player expanded just once */        \
    if (_plr_ && _plr_->ai && _plr_->ai->funcs._func) {                     \
      ai_timer_player_start(_plr_);                                         \
      _plr_->ai->funcs._func(__VA_ARGS__);                                  \
      ai_timer_player_stop(_plr_);                                          \
    }                                                                       \
  } while (false)

#define CALL_FUNC_EACH_AI(_func, ...)                                       \
  do {                                                                      \
    ai_type_iterate(_ait_)                                                  \
    {                                                                       \
      if (_ait_->funcs._func) {                                             \
        ai_timer_start(_ait_);                                              \
        _ait_->funcs._func(__VA_ARGS__);                                    \
        ai_timer_stop(_ait_);                                               \
      }                                                                     \
    }                                                                       \
    ai_type_iterate_end;                                                    \
  } while (false)
