#ifndef _NETWORK_EVENTS_H_
#define _NETWORK_EVENTS_H_

#include <utility>
#include "RKJson.h"
#include "RKTypes.h"
#include "Time/HighResolutionClock.h"
#include "Time/ServerTime.h"
#include "EventSystem.h"


// These are new style events created for OT


DECLARE_EVENT(LoginFederationEvent)

DECLARE_EVENT(ConnectionCreated)      // The raw interface is up
DECLARE_EVENT(ConnectionEstablished)  // Handshake completed
DECLARE_EVENT(ConnectionInDanger)     // Raised when the otherside isn't responding when expected
DECLARE_EVENT(ConnectionOutOfDanger)  // Raised when the otherside resumes responding after a temporary interruption
DECLARE_EVENT(ConnectionLost)         // If the connection is closed or we are in-danger too long and we close it

DECLARE_EVENT(GameDBRefresh)
DECLARE_EVENT(HestiaConfigRefresh)

DECLARE_EVENT(FullRestartStartedEvent)
//DECLARE_EVENT(ErrorWhileLoggingIntoAccountEvent)
//DECLARE_EVENT(AccountInactiveEvent)
//DECLARE_EVENT(AccountInactiveDisconnectedEvent)


// Below are the legacy events/actions that were used in ZA


enum NetworkEvent
{
  NetworkEvent_Connected,
  NetworkEvent_Disconnected,
  NetworkEvent_LoginFederation,
  NetworkEvent_ProfileRefreshed,
  NetworkEvent_GameSaved,
  NetworkEvent_GameLoaded,
  NetworkEvent_ServerDisconnect,
  NetworkEvent_AppLaunched,
  NetworkEvent_BandwidthProbeResult,
  NetworkEvent_ServerConnectionInDanger,  // Happens when the client doesn't hear from the server for some time
  NetworkEvent_ServerConnectionOutOfDanger, // After sending InDanger, if we hear from the server again, we send this
  NetworkEvent_ServerConfigReceived, 
  NetworkEvent_DLC,
  NetworkEvent_DLCSize,
  NetworkEvent_AccountLocked,
  NetworkEvent_ResumeNetworkThread,
  NetworkEvent_AccountWasUnlocked,
  NetworkEvent_ErrorWhileLoggingIntoAccount,
  NetworkEvent_DLCTextShow,
  NetworkEvent_DLCTextHide,
  NetworkEvent_FullScreenAdOff,
  NetworkEvent_DisplayAdError
};

struct BandwidthProbeResult
{
  GameTime::high_resolution_clock::duration m_roundTripTime;
  size_t m_payloadSize;
};

// TODO These probably don't live here long term (if we need them at all).
enum SavegameRequest
{
  SavegameRequest_Load,
  SavegameRequest_Save,
  SavegameRequest_SaveOther
};

enum SavegameResponse_LoadResult
{
  SavegameResponse_LoadResult_OK,
  SavegameResponse_LoadResult_Error,
  SavegameResponse_LoadResult_UnableToLock,
  SavegameResponse_LoadResult_FutureProgressBuffer,
  SavegameResponse_LoadResult_BufferContainsUnsupportedData,
  SavegameResponse_LoadResult_BadBuffer,
};

struct SavegameSaveUserData
{
  const void* m_pProfile = nullptr;
  bool m_bForceFlush = false;
  bool m_bKeepLocked = false;
  std::string m_credential;
};

struct SavegameLoadUserData
{
  SavegameLoadUserData(SavegameResponse_LoadResult a_eResult, bne::JsonValueConstRef a_jsonVal) : m_eResult(a_eResult), m_saveGameData(a_jsonVal)
  {
  }

  SavegameResponse_LoadResult m_eResult = SavegameResponse_LoadResult_Error;
  bne::JsonValue m_saveGameData = bne::JsonValueRef::null;
  std::string m_lockingCredential;
  bool m_bSelfLock = false;
};

enum SavegameResponse
{
  SavegameResponse_Load,
  SavegameResponse_Save
};

enum ProfileRequest
{
  ProfileRequest_Load,
  ProfileRequest_Lock,
  ProfileRequest_Unlock,
  ProfileRequest_Notification,
  ProfileRequest_CheckAdDelivery,
  ProfileRequest_CheckGiftDelivery,
  ProfileRequest_Update,
  ProfileRequest_CheckIAPTransactionDelivery,
  ProfileRequest_CheckInventory,
  ProfileRequest_UpdateCompatabilityHash,
  ProfileRequest_StartInactivityTimer,
  ProfileRequest_LoadBatch,
  ProfileRequest_CRMConfigRequested,
  ProfileRequest_GetLinkedCredentials,
  ProfileRequest_SaveProfileCustomData,
  ProfileRequest_ClearPendingTransactions,
  ProfileRequest_CRMConfigRequestedForLevelUp,
  ProfileRequest_MigrateBatch
};

enum ProfileResponse
{
  ProfileResponse_Load,
  ProfileResponse_Lock,
  ProfileResponse_Save,
  ProfileResponse_Unlock,
  ProfileResponse_CheckForRewards,
  ProfileResponse_CheckIAPTransactionDelivery,
  ProfileResponse_CheckInventory,
  ProfileResponse_MoveGiftToPendingRewards,
  ProfileResponse_DoInitialRewardCheck,
  ProfileResponse_DoInitialAchievementCheck,
  ProfileResponse_ClaimFacebookReward,
  ProfileResponse_Check_For_Received_Crew_Requests,
  ProfileResponse_Check_Crew_Status,
  ProfileResponse_LoadBatch,
  ProfileResponse_GetLinkedCredentials,
  ProfileResponse_Check_Sent_Crew_Requests_Status,
  ProfileResponse_SaveProfileCustomData,
  ProfileResponse_RemoveFromCrewOnReset,
  ProfileResponse_RemoveProcessedPendingTransaction,
  ProfileResponse_Check_Crew_Membership_Status,
  ProfileResponse_ClaimSinaWeiboReward
};

enum HermesRequest
{
  HermesRequest_CheckHermesMessages,
  HermesRequest_ClearHermesAlterDCMessage,
  HermesRequest_DeleteHermesMessage,
  HermesRequest_CustomerCareResetProfileRequest
};

enum HermesResponse
{
  HermesResponse_AddCustomerCareGiftToPendingRewards,
  HermesResponse_RemoveDeliveredCustomerCareGift,
};

enum LeaderboardRequest
{
  LeaderboardRequest_Update,
  LeaderboardRequest_GetEntries,
  LeaderboardRequest_GetLeagueInfo,
  LeaderboardRequest_DeleteEntry
};

enum LeaderboardType
{
  LEAGUE,
  GLOBAL,
  LOCAL,
  GEOLOCATED,
  FRIENDS,
  GLOBAL_CREW,
  INTERNAL_CREW,
  LT_MAX
};

struct LeaderBoardGetEntriesRequestUserData
{
  LeaderboardType m_type;
  size_t m_entryCount;
  size_t m_offset;
  std::string m_currentTier; // for league
  std::string m_country; // for local
  std::string m_crewId; // for crew internal list
  std::string m_credential; // To use for deleting leaderboard entries
};

enum CRMConfigEvent
{
  CrmConfig_GameDBUpdated,
  CrmConfig_GameDBReceived
};

struct CRMConfigEventData
{
  bool m_bSuccess = false;
  bool m_bRestartGame = false;
};

enum DataRequest
{
  DataRequest_Load,
  DataRequest_Save
};

enum DataResponse
{
  DataResponse_Load,
  DataResponse_Save
};

typedef std::pair<std::string, std::string> DataLoadRequestUserData;
struct DataSaveRequestUserData
{
  DataSaveRequestUserData(const std::string & a_credential, const std::string & a_key, const std::string& a_data, uint32_t a_expiry = 0)
    : m_credential(a_credential), m_key(a_key), m_data(a_data), m_expiry(a_expiry) {}

  std::string m_credential;
  std::string m_key;
  uint32_t m_expiry;
  const std::string m_data;
};

struct DataSaveResponseUserData
{
  DataSaveResponseUserData(const std::string& a_credential, const std::string& a_key, bool a_result)
    : m_credential(a_credential), m_key(a_key), m_result(a_result) {}

  std::string m_credential;
  std::string m_key;
  bool m_result;
};

struct DataLoadResponseUserData
{
  DataLoadResponseUserData(const std::string& a_credential, const std::string& a_key, const std::string& a_data)
    : m_credential(a_credential), m_key(a_key), m_data(a_data) {}

  std::string m_credential;
  std::string m_key;
  std::string m_data;
};

enum LeaderboardResponse
{
  LeaderboardResponse_Update,
  LeaderboardResponse_GetEntries,
  LeaderboardResponse_GetLeagueInfo
};

struct GetLeagueInfoResponseUserData
{
  Timestamp m_periodEnd;
};

typedef std::pair<bool, std::string> ProfileLoadRequestUserData;

struct  ProfileNotificationRequestUserData
{
  // todo - might need to include transport type?
  ProfileNotificationRequestUserData(const std::string & a_credential, const std::string & a_from, const std::string & a_body)
    : m_credential(a_credential), m_from(a_from), m_body(a_body) {}

  std::string m_credential;
  std::string m_from;
  std::string m_body;
};

struct ProfileBatchLoadRequestUserData
{
  ProfileBatchLoadRequestUserData(const std::string & a_credentialList, const std::string & a_includeFields)
    : m_credentialList(a_credentialList), m_includeFields(a_includeFields) {}

  std::string m_credentialList;
  std::string m_includeFields;
};

enum ProfileResponse_LoadResult
{
  ProfileResponse_LoadResult_OK,
  ProfileResponse_LoadResult_NotFound,
};

enum class ProfileLockStatus
{
  NotLocked,
  LockedByUs,
  LockedByOther,
  LockExpired,
  Unknown
};

enum ProfileResponse_SaveResult
{
  ProfileResponse_SaveResult_Processing,
  ProfileResponse_SaveResult_Queued,
  ProfileResponse_SaveResult_OK,
  ProfileResponse_SaveResult_Error,
};

enum ProfileResponse_LockResult
{
  ProfileResponse_LockResult_OK,
  ProfileResponse_LockResult_Updated,
  ProfileResponse_LockResult_Error,
  ProfileResponse_LockResult_NotSet
};

enum ProfileResponse_UnlockResult
{
  ProfileResponse_UnlockResult_OK,
  ProfileResponse_UnlockResult_Error
};

struct ProfileLoadResponseUserData
{
  ProfileLoadResponseUserData(const std::string & a_credential, ProfileResponse_LoadResult a_result, ProfileLockStatus a_lockStatus, bne::JsonValueConstRef a_pJSON)
    : m_credential(a_credential), m_result(a_result), m_lockStatus(a_lockStatus), m_pJSON(a_pJSON) {}

  std::string m_credential;
  ProfileResponse_LoadResult m_result;
  ProfileLockStatus m_lockStatus;
  bne::JsonValueConstRef m_pJSON;
};

struct ProfileSaveResponseUserData
{
  ProfileSaveResponseUserData(const std::string & a_credential, ProfileResponse_SaveResult a_result)
    : m_credential(a_credential), m_result(a_result) {}

  std::string m_credential;
  ProfileResponse_SaveResult m_result;
};

struct ProfileLockResponseUserData
{
  ProfileLockResponseUserData(const std::string & a_credential, ProfileResponse_LockResult a_lockResult, bne::JsonValueConstRef a_pJSON)
    : m_credential(a_credential), m_lockResult(a_lockResult), m_pJSON(a_pJSON) {}

  std::string m_credential;
  ProfileResponse_LockResult m_lockResult;
  bne::JsonValueConstRef m_pJSON;
};

struct ProfileUnlockResponseUserData
{
  ProfileUnlockResponseUserData(const std::string & a_credential, ProfileResponse_UnlockResult a_unlockResult)
    : m_credential(a_credential), m_unlockResult(a_unlockResult) {}

  std::string m_credential;
  ProfileResponse_UnlockResult m_unlockResult;
};

struct ProfileLinkedCredentialsResponseData
{
  explicit ProfileLinkedCredentialsResponseData(const std::string & a_credential)
    : m_initialCredential(a_credential) {}

  std::string m_initialCredential;
  std::vector< std::string > m_credentials;
};

struct ProfileSaveCustomDataRequestData
{
  ProfileSaveCustomDataRequestData(const std::string & a_saveKey, const std::string & a_sOperation, bne::JsonValueConstRef a_saveData)
    : m_saveKey(a_saveKey), m_operation(a_sOperation), m_saveData(a_saveData) {}

  std::string m_saveKey;
  std::string m_operation;
  bne::JsonValue m_saveData;
};

enum NetworkRequestEvent
{
  NetworkRequestEvent_Connect,
  NetworkRequestEvent_ServerVersion,
  NetworkRequestEvent_GameAction,
  NetworkRequestEvent_Disconnect,
  NetworkRequestEvent_InternalDisconnect,
  NetworkRequestEvent_ClientConfig,
  NetworkRequestEvent_UpdateSave,
};

enum NetworkResponseEvent
{
  NetworkResponseEvent_ServerVersion,
  NetworkResponseEvent_Connect,
  NetworkResponseEvent_GameAction,
  NetworkResponseEvent_InDanger,
  NetworkResponseEvent_ServerConfigReceived,
  NetworkResponseEvent_DeliverQueue,
  NetworkResponseEvent_ServerTracking
};

enum AchievementEventType
{
  AchievementEventType_Check,
  AchievementEventType_Update,
  AchievementEventType_Set,
  AchievementEventType_ResourceUpdate,
  AchievementEventType_ZombieUpdate,
  AchievementEventType_Unlock,
  AchievementEventType_Set_IfGreater
};

struct AchievementEventData
{
  AchievementEventData(int32_t a_iDataType, int32_t a_iValue)
    : m_iDataType(a_iDataType), m_iValue(a_iValue) {}

  int32_t m_iDataType;
  int32_t m_iValue;
};

enum CrewRequestType
{
  CrewRequest_Create,
  CrewRequest_GetCrews,
  CrewRequest_GetCrewMembers,
  CrewRequest_JoinCrewMember,
  CrewRequest_DeleteCrew,
  CrewRequest_RemoveFromCrew,
  CrewRequest_FindCrewByName,
  CrewRequest_Promote_Demote_Crew_Members,
  CrewRequest_Update,
  CrewRequest_Check_For_Crew_Requests,
  CrewRequest_Accept_Request,
  CrewRequest_Ignore_Request,
  CrewRequest_Get_Crew_Info_Request,
  CrewRequest_Get_Crew_Messages_Request,
  CrewRequest_Post_Crew_GiftRequest_Request,
  CrewRequest_Post_Crew_GiftResponse_Request,

  CrewRequest_Create_Response,
  CrewRequest_GetCrews_Response,
  CrewRequest_GetCrewMembers_Response,
  CrewRequest_JoinCrewMember_Response,
  CrewRequest_DeleteCrew_Response,
  CrewRequest_RemoveFromCrew_Response,
  CrewRequest_FindCrewByName_Response,
  CrewRequest_Promote_Demote_Crew_Members_Response,
  CrewRequest_Update_Response,
  CrewRequest_Check_For_Crew_Requests_Response,
  CrewRequest_Accept_Response,
  CrewRequest_Ignore_Response,
  CrewRequest_Get_Crew_Info_Response,
  CrewRequest_Get_Crew_Messages_Response,
  CrewRequest_Post_Crew_GiftRequest_Response,
  CrewRequest_Post_Crew_GiftResponse_Response,

  CrewRequest_Set_Field_Request,
  CrewRequest_Get_Field_Request,
  CrewRequest_Inc_Dec_Field_Request,

  CrewRequest_Set_Field_Response,
  CrewRequest_Get_Field_Response,
  CrewRequest_Inc_Dec_Field_Response,

  CrewRequest_Check_For_Sent_Crew_Requests,
  CrewRequest_Check_For_Sent_Crew_Requests_Response,
  CrewRequest_Cancel_Sent_Request,
  CrewRequest_Cancel_Sent_Response,
  CrewRequest_FindCrewByRecommendation,
  CrewRequest_FindCrewByRecommendation_Response,
  CrewRequest_Get_Osiris_Profile_Request,
  CrewRequest_Get_Osiris_Profile_Response,
  CrewRequest_Membership_Check,
  CrewRequest_Membership_Check_Response,
  CrewRequest_GetProfileTrophies_Request,
  CrewRequest_GetProfileTrophies_Response,
  CrewRequest_DeleteWallPost_Request,
  CrewRequest_DeleteWallPost_Response
};

struct CrewResponseEventData;
typedef std::function<void(const CrewResponseEventData *)> CrewCallback;

struct CrewRequestEventData
{
  std::string m_sOtherCredential;
  std::string m_sName;
  std::string m_sDescription;
  std::string m_sRequestType;
  std::string m_sId;
  std::string m_sRequestId;
  std::string m_sAvatar;
  std::string m_sPromoted;
  std::string m_sField;
  std::string m_sValue;
  std::string m_sOperation;
  uint32_t m_uiLimit = 20;
  uint32_t m_uiParam = 0;
  uint32_t m_uiMemberShipType = 0;
  uint32_t m_uiAmount = 0;
  bool m_bOwnersOnly = false;
  CrewCallback m_CrewRequestCallback = nullptr;
};

struct CrewResponseEventData
{
  std::string m_sData;
  std::string m_sErrorReason;
  std::string m_sId;
  CrewCallback m_CrewRequestCallback = nullptr;
  uint32_t m_uiErrorCode = 0;
  bool m_bHasError = false;
};

enum SocialServerRequestType
{
  SocialRequest_Filter_Message_Request,
  SocialRequest_Filter_Message_Response
};

struct SocialServerResponseData;
typedef std::function<void(const SocialServerResponseData *)> SocialServerCallback;

struct SocialServerRequestData
{
  std::string m_sMessage;
  std::string m_sLanguage;
  SocialServerCallback m_RequestCallback = nullptr;
};

struct SocialServerResponseData
{
  std::string m_sMessage;
  std::string m_sMessageResponse;
  SocialServerCallback m_RequestCallback = nullptr;
  bool m_bHasError = true;
};

enum ClientDisconnectRequestType
{
  ClientDisconnect_Connection_Closing,
  ClientDisconnect_Game_Action_Error
};

#endif
