// ################################
// ##           Protokol na srv  ##
// ##                            ##
// ################################

#pragma once
#ifndef PROTOCOL_SRV_H
#define PROTOCOL_SRV_H

#include "common.h"

#include <string>
#include <map>
#include <list>
#include <utility>

#include "datetime.h"
#include "science_tree.h"
#include "protocol.h"
#include "fortress_skelet.h"

void write_scientific_tree(protocolWriter& w, scientificTree* sc);

class answerWriter
{
public:
    static char* chat(unsigned long sender, unsigned long recipient, const std :: string& message, dv_time:: datetime dt);
    static char* buddy(const std :: list<std :: pair<unsigned long, std :: string>>& buddies);
    static char* planets_nonexisting(unsigned long areaid);
    static char* planets_notstar(unsigned long areaid);
    static char* planets_ie(unsigned long areaid);
    static char* shipsinarea_notexisting(unsigned long shipid);
    static char* shipsinarea_notown(unsigned long shipid);
    static char* shipsinarea_inwarp(unsigned long shipid);
    static char* shipsinarea_ie(unsigned long shipid);

    static char* navigation_ship_not_exists(unsigned long shipid, const std :: string& request);
    static char* navigation_ship_not_owned(unsigned long shipid, const std :: string& request);
	static char* navigation_ship_not_controllable(unsigned long shipid, const std :: string& request);
    static char* navigation_ship_in_warp(unsigned long shipid, const std :: string& request);
    static char* navigation_ship_not_in_warp(unsigned long shipid, const std :: string& request);
    static char* navigation_ship_docked_in_base(unsigned long shipid, const std :: string& request);
    static char* navigation_ship_target_not_exits(unsigned long shipid, const std :: string& request);
    static char* navigation_ship_target_not_in_normal_space(unsigned long shipid, const std :: string& request);
    static char* navigation_OK(const std :: string& request, unsigned long shipid);
    static char* navigation_FAIL(const std :: string& request, unsigned long shipid);
	static char* navigation_dock_down(unsigned long shipId, unsigned long baseId, dockingResult result);
	static char* navigation_unbound(unsigned long shipId, dockingResult result);

    static char* ship_journey_details_FAIL(const unsigned long shipid, const std :: string& reason);
    static char* ship_journey_details_STANDARD(const unsigned long shipid, const dist_t positionx,
        const dist_t positiony, const char* state, const char* target, unsigned long long speed,
        unsigned long long acceleration, bool isDockedInBase, dockingResult result);
    static char* ship_journey_details_PURSUIT(const unsigned long shipid, const char* state, const char* target,
        unsigned long targetShip, dist_t estimation_distance, const dv_time:: datetime estimation_time,
        const dist_t positionx, const dist_t positiony, unsigned long long speed,
        unsigned long long acceleration, dockingResult result);
    static char* ship_journey_details_MOVE_TO_POS(const unsigned long shipid, const char* state, const char* target,
        const dist_t dposx, const dist_t dposy, const dist_t estimation_distance, 
        const dv_time:: datetime estimation_time, const dist_t positionx, const dist_t positiony, unsigned long long speed,
        unsigned long long acceleration, dockingResult result);
    static char* ship_journey_details_MOVE_TO_SPACE_OBJECT(const unsigned long shipid, const char* state, const char* target,
        unsigned long targetSpaceObject, const std :: string& spObjName, dist_t estimation_distance, 
        const dv_time:: datetime estimation_time, const dist_t positionx, const dist_t positiony, unsigned long long speed,
        unsigned long long acceleration, dockingResult result);
    static char* device_energy_state(const unsigned long ship, const answerDeviceEnergy& de);
    static char* device_energy_state_error(const unsigned long ship, const char* reason);
    static char* change_device_energy_state_error(const unsigned long ship, const char* reason);
    static char* science(scientificTree* scTree);
    static char* science_change(scientificTree* scTree);
    static char* science_ie(void);
    static char* science_change_ie(void);
    static char* ship_central_information(fortressClass* shp);
    static char* ship_central_information_FAIL(const unsigned long shipid, const std :: string& reason);

    static char* ships(const std :: list<shipClass*>& ships);
    static char* bases(const std :: list<baseClass*>& bases);
    static char* ship_subspace_drive_information(const unsigned long shipid, const subspace_drive_status& sds);
    static char* ship_subspace_drive_information_FAIL(const unsigned long shipid, const std :: string& reason);
    static char* ship_impulse_drive_information(const unsigned long shipid, const impulse_drive_status& sds);
    static char* ship_impulse_drive_information_FAIL(const unsigned long shipid, const std :: string& reason);
    static char* ship_location_information(const unsigned long shipid, const location_status& ls);
    static char* ship_location_information_FAIL(const unsigned long shipid, const std :: string& reason);

    static char* fortress_shields_information(fortressClass* shp);
    static char* fortress_shields_information_FAIL(const unsigned long fortressid, const std :: string& reason);
    static char* fortress_weapons_information(const unsigned long fortressid, const weapons_status& sds);
    static char* fortress_weapons_information_FAIL(const unsigned long fortressid, const std :: string& reason);
    static char* fortress_weapons_set(const unsigned long fortressid, const weapons_status& sds);
    static char* fortress_weapons_set_FAIL(const unsigned long fortressid, const std :: string& reason);
    static char* fortress_mainframe_information(const unsigned long fortressid, const mainframe_status& sds);
    static char* fortress_mainframe_information_FAIL(const unsigned long fortressid, const std :: string& reason);
    static char* fortress_crew_information(const unsigned long fortressid, const crew_status& sds);
    static char* fortress_crew_information_FAIL(const unsigned long fortressid, const std :: string& reason);
    static char* fortress_quarry_information(const unsigned long fortressid, const quarry_status& qs);
    static char* fortress_quarry_information_FAIL(const unsigned long fortressid, const std :: string& reason);
    static char* fortress_quarry_change_state_FAIL(const unsigned long fortressid, const std :: string& reason);
	static char* fortress_accommodations_information(const unsigned long fortressid, const accommodation_status & sds);
	static char* fortress_accommodations_information_FAIL(const unsigned long fortressid, const std :: string& reason);
	static char* fortress_other_equipment_information(const unsigned long fortressid, const other_equipment_status & sds);
	static char* fortress_other_equipment_information_FAIL(const unsigned long fortressid, const std :: string& reason);
	static char* base_factories_information(const unsigned long baseId, const factories_status & sds);
	static char* base_factories_information_FAIL(const unsigned long baseId, const std :: string& reason);
	static char* fortress_warehouses_information(const unsigned long baseId, const warehouses_status & sds);
	static char* fortress_warehouses_information_FAIL(const unsigned long baseId, const std :: string& reason);

	static char* ship_androids_information(const unsigned long baseId, const ship_androids_status & sds);
	static char* ship_androids_information_FAIL(const unsigned long baseId, const std :: string& reason);
	static char* base_androids_information(const unsigned long baseId, const base_androids_status & sds);
	static char* base_androids_information_FAIL(const unsigned long baseId, const std :: string& reason);

	static char* change_ship_androids_state_FAIL(const unsigned long fortressId, const std :: string& reason);
	static char* change_base_androids_state_FAIL(const unsigned long fortressId, const std :: string& reason);
	static char* base_hangars_information(const unsigned long fortressId, const hangars_status & sds);
	static char* base_hangars_item_information(const hangar_item_status & sds);
	static char* base_hangars_information_FAIL(const unsigned long fortressId, const std :: string& reason);
	
	static char* base_hangar_build_item(unsigned long fortressId, unsigned long hangarId, itemsCreationResult result);
	static char* base_hangar_build_item_FAIL(unsigned long fortressId, unsigned long hangarId, const std :: string& reason);
	static char* base_hangar_cancel_item(unsigned long fortressId, unsigned long hangarId);
	static char* base_hangar_cancel_item_FAIL(unsigned long fortressId, unsigned long hangarId, const std :: string& reason);

	static char* unmount_fortress_device(const unmount_device_info & mountData, const std :: string& mountingResult);
	static char* unmount_fortress_device_FAIL(unsigned long fortressId, const std::string& patternName, const std :: string& reason);
	
	static char* mount_fortress_device(unsigned long fortressId, unsigned long itemId, const std :: string& mountingResult);
	static char* mount_fortress_device_FAIL(unsigned long fortressId, unsigned long itemId, const std :: string& reason);

	static char* navigation_planets_FAIL(const unsigned long shipId, const std :: string& reason);
    static char* navigation_planets_nonexisting(unsigned long areaid);
    static char* navigation_planets_notstar(unsigned long areaid);
    static char* navigation_planets_ie(unsigned long areaid);

    static char* player_discovered_stars(const discovered_stars& ds);

	static char* send_trade_invitation(const trade_invitation_data & invitation, const std::string & reason, tradingRole tradeRole);	
	static char* send_trade_invitation(const trade_invitation_data & invitation, const trade_data & selfTradeData, const std::string & reason, tradingRole tradeRole);	
	static char* send_trade_invitation(const trade_invitation_data & invitation, const trade_data & selfTradeData, const trade_data & partnerTradeData, const std::string & reason, tradingRole tradeRole);	
	static char* send_trade_invitation_FAIL(const std::string & reason);
	static char* cancel_trade(unsigned long ownedFortressId, unsigned long partnerFortressId, const std::string & reason, tradingRole tradeRole);
	static char* cancel_trade_FAIL(unsigned long ownedFortressId, unsigned long partnerFortressId, const std::string & reason);
	static char* receive_trade_invitation(const trade_invitation_data & invitation);
	static char* receive_cancel_trade(unsigned long ownedFortressId, unsigned long partnerFortressId);
	static char* trade_partner_fortresses(unsigned long fortressId, const std::list<fortressClass*> & ownedFortresses, const std::list<fortressClass*> & notOwnedFortresses);	
	static char* trade_partner_fortresses_FAIL(unsigned long ownedFortressId, const std::string & reason);
	static char* receive_trade_invitation_decision(const trade_invitation_data & invitation);
	static char* receive_trade_invitation_decision(const trade_invitation_data & invitation, const trade_data & tradeData);
	static char* decide_trade_invitation(const trade_invitation_data & invitation);	
	static char* decide_trade_invitation(const trade_invitation_data & invitation, const trade_data & tradeData);	
	static char* decide_trade_invitation_FAIL(unsigned long hostFortressId, unsigned long invitedFortressId, const std :: string& reason);
	static char* move_trade_item(unsigned long selfFortressId, unsigned long partnerFortressId, unsigned long itemId, const std::string & tradeDirection);
	static char* move_trade_item(const trade_movement_data & tradeData, bool isAuthor);
	static char* move_trade_item_FAIL(const trade_client_movement_data & tradeData, const std::string & reason);
	static char* commit_trade_FAIL(unsigned long selfFortressId, unsigned long partnerFortressId, const std::string & reason);
	static char* commit_trade(unsigned long selfFortressId, unsigned long partnerFortressId, tradingResult result);
	static char* prepare_commit_trade(unsigned long selfFortressId, unsigned long partnerFortressId, tradingCommitRole role);
	static char* move_trade_resource(const trade_resource_movement_data & tradeData, bool isAuthor);
	static char* move_trade_resource_FAIL(const trade_resource_movement_data & tradeData, const std::string & reason);
	static char* cancel_trade_commit(unsigned long selfFortressId, unsigned long partnerFortressId, const std::string & reason);
	static char* cancel_trade_commit_FAIL(unsigned long selfFortressId, unsigned long partnerFortressId, const std::string & reason);
	static char* fortresses_in_weapons_range(fortressClass * fortress, const std::list<shipClass*> & ships, const std::list<baseClass*> & bases);
	static char* fortresses_in_weapons_range_FAIL(unsigned long fortressId, const std::string & reason);
	static char* attack_fortress(unsigned long selfFortressId, unsigned long enemyFortressId);
	static char* attack_fortress_FAIL(unsigned long selfFortressId, unsigned long enemyFortressId, const std::string & reason);
	static char* stop_attack_fortress(unsigned long selfFortressId);
	static char* stop_attack_fortress_FAIL(unsigned long selfFortressId, const std::string & reason);

	static char* fight_action_report(fortressClass * selfFortress, fortressClass * enemyFortress, fight_action_type action);
	static char* fortresses_in_conquer_range(fortressClass * selfFortress, const std::list<fortressClass*>& ownedFortresses, const std::list<fortressClass*>& notOwnedFortresses);
	static char* fortresses_in_conquer_range_FAIL(unsigned long selfFortressId, const std::string & reason);
	static char* build_new_base_shell(unsigned long selfFortressId, baseBuildingResult result, unsigned long long newTitan);
	static char* build_new_base_shell_FAIL(unsigned long selfFortressId, const std::string & result);
	static char* available_fortress_classes(fortressClass * selfFortress, const std::list<fortressClassClass*>& shipClasses, const std::list<fortressClassClass*>& baseClasses);
	static char* available_fortress_classes_FAIL(unsigned long fortressId, const std::string & reason);
	static char* fortress_class_data(fortressClassClass* fortessClazz);
	static char* fortress_class_data_FAIL(unsigned long fortressClassId, const std::string & reason);
	static char* player_fortresses_build_information(const std::list<shipClass*>& ships, const std::list<baseClass*>& bases);
	static char* conquer_fortress(unsigned long selfFortressId, unsigned long targetFortressId, fortressAddingResult addingResult, conquerResultClass conquerResult);
	static char* conquer_fortress_FAIL(unsigned long selfFortressId, const std::string & reason);
	static char* fortress_add_accommodations(unsigned long fortressid, unsigned long count, accommodation_type accommodationType);
	static char* fortress_add_accommodations_FAIL(unsigned long fortressid, const std::string & reason);
	static char* fortress_add_crew(unsigned long fortressid, unsigned long able, unsigned long wounded, crew_type crewType);
	static char* fortress_add_crew_FAIL(unsigned long fortressid, const std::string & reason);
	static char* fortress_remove_crew(unsigned long fortressid, unsigned long able, unsigned long wounded, crew_type crewType);
	static char* fortress_remove_crew_FAIL(unsigned long fortressid, const std::string & reason);
	static char* player_fortresses(const std :: list<shipClass*>& ships, const std :: list<baseClass*>& bases);
	static char* game_seconds_per_actual_second(unsigned long value);
	static char* rename_fortress(unsigned long fortressId, const std::string & newName);
	static char* rename_fortress_FAIL(unsigned long fortressId, const std::string & reason);
	static char* player_fortresses_attack_information(const std::list<shipClass*>& ships, const std::list<baseClass*>& bases);
	static char* base_hangar_build_new_ship(unsigned long fortressId, unsigned long hangarId, itemsCreationResult result);
	static char* base_hangar_build_new_ship_FAIL(unsigned long fortressId, unsigned long hangarId, const std :: string& reason);

	static char* fortress_sensors_information(unsigned long fortressId, const sensors_data & hrData, const sensors_data & lrData);
	static char* fortress_sensors_information_FAIL(unsigned long fortressId, const std::string & reason);

	static char* fortress_cloaking_information(unsigned long fortressId, const cloaking_data & data);
	static char* fortress_cloaking_information_FAIL(unsigned long fortressId, const std::string & reason);

    static char* ship_warp_information(const WarpInfo& winfo);
    static char* ship_warp_information_FAIL(unsigned long shipId, const std::string & reason);

	static void write_fortress_detailed_fight_data(protocolWriter & w, fortressClass * fortress, unsigned long index);
private:
	static void write_warehouse_item(protocolWriter& writer, const std::string & prefix, int index, const warehouse_item_status & item);
	static void write_warehouse_items_list(protocolWriter & w, const std::string & prefix, const warehouses_status::items_list_t & tradeData);
	static void write_androids_assignment(protocolWriter& w, const std::string & section, const androids_assignment & assignment);
	static void write_androids_status(protocolWriter& w, const androids_status & sds);
	static void write_trade_invitation(protocolWriter & w, const trade_invitation_data & invitation);
	static void write_trade_movement_data(protocolWriter & w, const trade_movement_data & tradeData);
	static void write_trade_start_data(protocolWriter & w, const std::string & prefix, const trade_data & tradeData);	
	static void write_sensors_data(protocolWriter & w, const std::string & prefix, const sensors_data & tradeData);		
};

class adminAnswerWriter {
public:
	static char* players(const std :: list<realm_information>& realms);
	static char* player_information(const realm_information & realmState, const std :: list<shipClass*>& ships, const std :: list<baseClass*>& bases);
	static char* create_ship(unsigned long playerId, shipClass * ship, bool shipCreated);
	static char* ship_information(shipClass * ship);
	static char* base_information(baseClass * ship);
	static char* ban_player(unsigned long playerId, const std::string & result, bool hasBan);
	static char* player_ban_information(unsigned long playerId, const banClass * ban);
};

bool ulong2bool(unsigned long value);
unsigned long bool2ulong(bool value);
std::string tradingRoleToString(tradingRole tradeRole);

#endif