/******************************************************************
  
  Module:  netpacket.h
  
  Author: Sean Craig
  
  
  Copyright 2005 Sony Online Entertainment.  All rights reserved.
  
*******************************************************************/

#ifndef NETPACKET_H
#define NETPACKET_H

//-------------------------------------------------------- Includes
//#include "gameobj.h"
#include "animdefs.h"
#include "nameid.h"
#include "SyPack.h"
#include "SyPropObject.h"


//-------------------------------------------------------- Typedefs
typedef tGameID tGameObjectID;

//---------------------------------------------- Class Declarations

class cNetPacket : public SyPack::Object
{
public:

  typedef enum
  {
    NET_POSITION,
    NET_ANIMSTATE,
    NET_DAMAGE,
    NET_ACTIVATE_REQUEST,
    NET_ACTIVATE_CONFIRM,
    NET_DROP,
    NET_AIBLACKBOARD,
    NET_SCRIPT_FUNC,
    NET_PUSH_REQUEST,
    NET_TRANSITION_LEVEL,
    NET_KNOCKBACK,
    NET_ADD_CONDITION,
    NET_REMOVE_CONDITION,
    NET_REMOVE_CONDITIONS_FROM_SOURCE,
    NET_RESET_OBJECT,
    NET_CAST_SPELL,
    NET_GLOBAL_SCRIPT_STATE,
    NUM_NETWORK_PACKET_TYPES,
  } eNetPacketType;

  cNetPacket(eNetPacketType type) : mType(type){};

  virtual void Pack(SyPack::DataStream *stream);

  eNetPacketType mType;
};

class cNetPositionPacket : public cNetPacket
{
public:
  cNetPositionPacket(); 
  virtual void Pack(SyPack::DataStream *stream);

  SyVect3 mLocation;
  SyVect3 mVelocity;
  SyVect3 mHPR;
  float   mSpeedRequest;
  float   mHeadingRequest;
  bool    mbTeleport;
};

class cNetAnimStatePacket : public cNetPacket
{
public:
  cNetAnimStatePacket() : cNetPacket(NET_ANIMSTATE){};
  virtual void Pack(SyPack::DataStream *stream);

  int                             mAnimState;
  tGameObjectID                   mTarget;
  tGameObjectID                   mActionTarget;
  float                           mTargetHeading;
  float                           mTargetRange;
  int32                           mScriptAnimID; // override whatever animation is playing with this AnimID.
  bool                            mScriptAnimAllowHitReactions; // override whatever animation is playing with this AnimID.
  tGameID                         mCastSpellID;
  int                             mCastAnimSettingOverride;
};

class cNetDamagePacket : public cNetPacket
{
public:
  cNetDamagePacket() : cNetPacket(NET_DAMAGE){};
  virtual void Pack(SyPack::DataStream *stream);

  int                             mTotalDamage; // on the character
  tGameObjectID                   mAttacker;
  bool                            mDeath;
  bool                            mHitReact;
  float                           mHitReactTime;
  int                             mDamageType;
};

class cNetActivateRequestPacket: public cNetPacket
{
public:
  cNetActivateRequestPacket() : cNetPacket(NET_ACTIVATE_REQUEST){};
  virtual void Pack(SyPack::DataStream *stream);

  tGameObjectID                   mActor;
};

class cNetActivateConfirmPacket: public cNetPacket
{
public:
  cNetActivateConfirmPacket() : cNetPacket(NET_ACTIVATE_CONFIRM){};
  virtual void Pack(SyPack::DataStream *stream);

  tGameObjectID                   mActor;
};

class cNetDropPacket: public cNetPacket
{
public:
  cNetDropPacket() : cNetPacket(NET_DROP){};
  virtual void Pack(SyPack::DataStream *stream);

  tGameObjectID                   mObject;
};

class cNetAIBlackboardPacket : public cNetPacket
{
public:
  cNetAIBlackboardPacket() : cNetPacket(NET_AIBLACKBOARD){};
  virtual void Pack(SyPack::DataStream *stream);

  char            mRecordType;
  tGameObjectID   mSourceID;
  tGameObjectID   mTargetID;
  unsigned int    mData;
  SyVect3         mLocation;
  bool            mbRemoveIfExists;
};



#if 0 // sgc: haven't decided to implement this or not
class cNetIntObjectPropertyPacket : public cNetPacket
{
public:

  typedef enum
  {
    NPOT_GAMEOBJECT,
    NPOT_GRAPHIC,
    NPOT_PHYSICS,
    NPOT_STATS,
    NPOT_INTEL,
    NPOT_INVENTORY,
    
  } eNetPropObjectType; 

  cNetIntObjectPropertyPacket() : cNetPacket(NET_OBJPROPCHANGE){};

  virtual void Pack(SyPack::DataStream *stream);
  
};
#endif

class Titan;
// this class is a little more complicated than the others; when a packet 
// is run across the network, it's the runtime data struct passed in as an 
// argument 
class cNetScriptFuncPacket: public cNetPacket
{
public:
  cNetScriptFuncPacket() : cNetPacket(NET_SCRIPT_FUNC),mIDENTIFIER(REMOTE_IDENTIFIER){};
  virtual void Pack(SyPack::DataStream *stream);
  bool GetAddr(int32 address,int32 **pdtr);
  bool GetString(char *buffer,int32 src, int max_string_len);

  void Init(SyResourceID func_index,int32* params, int numParams);
  void AddString(int cell_index, char *string);
  static const int MAX_NUM_PARAMS = 10;
  static const int MAX_STRING = 256;

  static const int REMOTE_IDENTIFIER = 0xDEADBEEF;
  static const int TEST_IDENTIFIER = 0xDEADBEAD;
  int          mIDENTIFIER;
  Titan       *mpTitan;
  SyResourceID mFuncID;
  int          mNumParams;
  int          mNumChars;
  int32        mParams[MAX_NUM_PARAMS];
  char         mStrings[MAX_STRING];
};


class cNetGlobalScriptStatePacket: public cNetPacket
{
public:
  cNetGlobalScriptStatePacket();
  virtual ~cNetGlobalScriptStatePacket();
  virtual void Pack(SyPack::DataStream *stream);

  struct ScriptInstanceData
  {
    ScriptInstanceData();
    ~ScriptInstanceData();

    int                 mParentIndex;
    tGameObjectID       mThisID;
    tGameObjectID       mOtherID;
    char*               mpScriptDelta;
    int                 mDeltaSize;
    int                 mSleepNotifyType;
    float               mSleepTime;
    tGameObjectID       mSleepingID;
    bool                mbCutscene;

    // amx register values
    int mAMX_cip;
    int mAMX_frm;
    int mAMX_hea;
    int mAMX_hlw;
    int mAMX_stk;
    int mAMX_stp;
  };

  void AddScript(int parentIndex,
                 tGameObjectID thisID, tGameObjectID otherID,
                 char* pSourceScript, char* pCurScript, int scriptSize,
                 int sleepNotifyType, float sleepTime,
                 tGameObjectID sleepingID, bool bCutscene,
                 int cip, int frm, int hea, int hlw, int stk, int stp);

  int GetNumScripts();
  const ScriptInstanceData* GetScriptData(int index);

  static const int MAX_CUTSCENEENDHANDLER_NAME_LEN = 64;

  bool       mbStartup;
  char       mCutsceneEndHandler[MAX_CUTSCENEENDHANDLER_NAME_LEN];
  float      mCutsceneSkipTime;
  bool       mCutsceneSkipping; 
  bool       mCutsceneEndFadeIn; 

protected:
  int                           mNumScripts; 
  SyVector<ScriptInstanceData*> mScripts; 
};

class cNetPushRequestPacket : public cNetPacket
{
public:
  cNetPushRequestPacket() : cNetPacket(NET_PUSH_REQUEST){};
  virtual void Pack(SyPack::DataStream *stream);

  SyVect3 mLocation;
};

class cNetTransitionLevelPacket : public cNetPacket
{
public:
  cNetTransitionLevelPacket() : cNetPacket(NET_TRANSITION_LEVEL){};
  virtual void Pack(SyPack::DataStream *stream);

  void Init(const char *levelname,const char *spawnpoint);

  static const int MAX_STRING = 256;
  char      mLevelName[MAX_STRING];
  char      mSpawnPointName[MAX_STRING];
};

class cNetKnockbackPacket : public cNetPacket
{
public:
  cNetKnockbackPacket() : cNetPacket(NET_KNOCKBACK){};
  virtual void Pack(SyPack::DataStream *stream);

  SyVect3           mLocation;
  float             mXZAmount;
  float             mYAmount;
  bool              mbKnockdown;
  float             mKnockdownTime;
};

class cNetAddConditionPacket : public cNetPacket
{
public:
  cNetAddConditionPacket() : cNetPacket(NET_ADD_CONDITION){};
  virtual void Pack(SyPack::DataStream *stream);

  static const int MAX_CONDITION_NAME_LEN = 32;

  char  mConditionName[MAX_CONDITION_NAME_LEN+1];
  tGameObjectID   mSourceID;
  tGameID   mSpellID;
  tGameID   mItemMasterID;
  float     mDuration;
  tGameID   mEffectID;
  int       mParam1;
  int       mParam2;
};

class cNetRemoveConditionPacket : public cNetPacket
{
public:
  cNetRemoveConditionPacket() : cNetPacket(NET_REMOVE_CONDITION){};
  virtual void Pack(SyPack::DataStream *stream);

  char            mConditionName[cNetAddConditionPacket::MAX_CONDITION_NAME_LEN+1];
  tGameObjectID   mSourceID;
  tGameID         mSpellID;
  tGameID         mItemMasterID;

};

class cNetRemoveConditionsFromSourcePacket : public cNetPacket
{
public:
  cNetRemoveConditionsFromSourcePacket() : cNetPacket(NET_REMOVE_CONDITIONS_FROM_SOURCE){};
  virtual void Pack(SyPack::DataStream *stream);

  tGameObjectID   mSourceID;
  tGameID         mSpellID;
  tGameID         mItemMasterID;
};


class cNetResetObjectPacket : public cNetPacket
{
public:
  cNetResetObjectPacket() : cNetPacket(NET_RESET_OBJECT){};
};

class cNetCastSpellPacket : public cNetPacket
{
public:
  cNetCastSpellPacket() : cNetPacket(NET_CAST_SPELL), mTargetID(ID_NONE), mSpellID(ID_NONE), mTargetLoc(0.0f, 0.0f, 0.0f), mCombo(NUM_COMBOS) {};
  virtual void Pack(SyPack::DataStream *stream);

  tGameObjectID   mTargetID;
  tGameID         mSpellID;
  SyVect3         mTargetLoc;
  int             mCombo;
};

class cDeltaCompression
{
public:

  static bool CreateDelta(char* pBase, int baseSize,
                          char* pTarget, int targetSize,
                          char* pDelta, int deltaSize,
                          int& deltaOutLen);

  static bool ApplyDelta(char* pBase, int baseSize,
                         char* pDelta, int deltaSize,
                         char* pTarget, int targetSize,
                         int& targetOutLen);

protected:
  enum Codes
  {
    DELTA_COPY        = 0x00,
    DELTA_INSERT      = 0x01,
  };
};


#endif
