#pragma once

#include <client.h>

#include <cstdint>

#include "skill/SkillID.h"
#include "skill/SkillProperty.h"

#include "object/mover/Mover.h"

namespace flyff {
// Find this is f195_calls_websocket_send
    const uint32_t PACKET_HEADER_HASH = 0x644ab000;

    namespace raw {
        static const auto &init = &Z_client_init;

        static const auto &_wasm_call_ctors = &Z_clientZ____wasm_call_ctors;
        static const auto &main = &Z_clientZ__main;

        static const auto &malloc = &Z_clientZ__malloc;
        static const auto &free = &Z_clientZ__free;
    }  // namespace raw

    class Neuz {
        Neuz();

        const Pointer<uintptr_t> &messages_ui;
        const Pointer<uintptr_t> &announcements_ui;

    protected:
        Neuz(Neuz const &) = default;

    public:
        static Neuz &instance();

        void operator=(Neuz const &) = delete;

        MoverMap const &movers;
        const Pointer<Mover> &player;
        const MoverID &player_object_id;

        const uint64_t &current_time;
        const uint64_t &start_time;
        const uint64_t &maybe_login_time;

        // Execute the `main` function of the flyff-client.
        int main() const;

        Pointer<Mover> get_mover(flyff::MoverID id) const;

        flyff::String get_text(const std::string &id) const;

        void show_message(const std::string &message,
                          const flyff::Color &color = {0xFF, 0xFF, 0xFF}) const;

        void show_announcement(const std::string &message,
                               const flyff::Color &color = {0xFF, 0xFF, 0xFF}) const;

        bool is_valid_attack(const Pointer<Mover> &attacker, const Pointer<Mover> &defender) const;

        static Pointer<SkillProperty> get_skill_property(const SkillID& id) ;

        // Easy to implement: Just send a EmscriptenKeyboardEvent* to the registered
        // function. void send_keydown(); void send_keyup(); void send_keypress();
    };
}  // namespace flyff