/******************************************************************
  
  Module:  cameracontroller.h
  
  Author: Sean Craig
  
  Description: Responsible for updating the camera from frame to 
  frame.  An interface wrapper around Bijan's stuff. 

  
  Copyright 2005 Sony Online Entertainment.  All rights reserved.
  
*******************************************************************/

#ifndef CAMERACONTROLLER_H
#define CAMERACONTROLLER_H

//---------------------------------------------- ---------- Includes
#include "nameid.h"
#include "Titan.h"
#include "SyCamera.h"
#include "transient.h"
//-------------------------------------------------------- Typedefs
//---------------------------------------------- Class Declarations

class TiCameraDirector;

typedef enum
{
  CAMERA_NONE=-1,
  CAMERA_NEAR,
  CAMERA_FAR,
  CAMERA_TWOPLAYER,
  CAMERA_CUTSCENE,
  CAMERA_SCRIPT_LOOKAT1,
  CAMERA_TRANSITION,
  CAMERA_SCRIPT_LOOKAT2,
  CAMERA_SCRIPT_LOOKAT3,
  CAMERA_FREE,
  NUM_CAMERA_TYPES
} eCameraSetting;




class cCameraAI;

class cCameraController
{
public:

  cCameraController(Titan *titan);
 
  ~cCameraController();
  /// Initializes the application
  bool OnInit();

  /// Called on exit
  void OnExit();

  static void RegisterTuningVariables();
  void LoadCameraFile(const char *camFileName);

  void SetTarget(tGameID id);
  void SetTargetTwoPlayer(tGameID id,tGameID id2); // dual camera
  bool HitTether(tGameID id, SyVect3 &start, SyVect3 &end,float radius);

  void Update(float time); 
  SyCamera *GetCamera(){return &mCamera;};

  // returns the camera heading to be used for camera-relative controls
  // time_held_down is the amount of time the controller has been depressed;
  // this is used when the camera cuts to introduce a lag to give the player
  // a chance to respond to the switched camera.

  float GetControlOffset(float time_held_down);

  // Mechanism to allow for outside modules to override normal camera controller camera.
  bool UseOverrideCamera();
  void OverrideCamera (const SyVect3& cameraPosition, const SyVect3& cameraDirection, const float32& cameraFov);
  void ClearOverrideCamera ();

  void Zoom(float amount);
  void Pan(float amount);
  void SetHeading(float heading);

  void ReverseCameraPan(bool bReverse) { mbReverse = bReverse; }
  
  void RequestHeading(float heading);

  void StartScriptCamLookAt(eCameraSetting setting,
                            tGameID source, 
                            tGameID target,
                            float sourceYOffset=0.0f,
                            float targetYOffset=0.0f);

  void ScriptTransition(eCameraSetting setting, float vel,float acceleration);
  void ScriptCut(eCameraSetting setting);

  SyVect3 GetCameraLocation(eCameraSetting setting);
  float GetCameraHeading(eCameraSetting setting);
  void  SetCameraHeading(eCameraSetting setting,float heading);

  void EndScriptCam();

  void Shake(float delay, float shakeMagnitude, float oscSpeed, float durationSeconds);


  cCameraAI *GetCameraAI(eCameraSetting setting);
  void       Cut(eCameraSetting setting);
  eCameraSetting GetUserSetting(){return mUserSetting;};
  eCameraSetting GetScriptSetting(){return mScriptSetting;};

  void  EnableFreeCam();
  void  DisableFreeCam();

  void  SetMaxDistance(eCameraSetting setting,float max_distance);
  Titan *GetTitan(){return mTitan;}
protected:

  // utility function that returns the aspect ratio of the display device
  float GetAspectRatio();

  void  SettingUp();
  void  SettingDown();
  void  HandleCameraShake(tGameID id, SyVect3 &Cam_Dir,SyVect3 &Cam_Loc);
  void  ChooseCamera();

  Titan   *         mTitan;
  SyCamera          mCamera;
  TiCameraDirector *mDirector;
  float32           mCutTime;
  SyVect3           mCutDir;
  bool              mCutStored;

  bool              mbTwoPlayer;
  bool              mbReverse;

  bool              mPrevDirStored;
  SyVect3           mPrevDir;

  bool              mbCutsceneCam;
  eCameraSetting    mUserSetting; // when not overridden by other cameras
  eCameraSetting    mScriptSetting; // choice from scripting camera

  uint64            mLastShake;
  float             mShakeMagnitude;
  float             mShakeDuration;
  float             mShakeSpeed;
  float             mShakeDelay;

  float             mfAspectRatio;
  float             mfPlayerDistance; // from each other, in 2p mode

  typedef enum
  {
    SETTING_CHANGE_DOWN,
    SETTING_CHANGE_NONE,
    SETTING_CHANGE_UP
  } eSettingChangeState;

  eSettingChangeState mSettingChangeState;
  float             mSettingChangeTime;

  eCameraSetting    mSetting;
  cCameraAI *       mCameraAIs[NUM_CAMERA_TYPES];
  
};

//------------------------------------------- Function Declarations
//--------------------------------------------------------- Globals
//------------------------------------------------ Inline Functions

#endif
