/* bzflag
 * Copyright (c) 1993-2017 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */

/*
 * ShotPath:
 *	Encapsulates the path a shot follows.  Most paths can
 *	be computed at the instant of firing (though they may
 *	terminate early because of a hit).  Some paths need
 *	to be updated continuously during flight.
 *
 * RemoteShotPath:
 *	A ShotPath acting as a proxy for a remote ShotPath.
 *	Created by a LocalPlayer on behalf of a RemotePlayer.
 */

#ifndef	__SHOTPATH_H__
#define	__SHOTPATH_H__

#include "common.h"

/* common interface headers */
#include "TimeKeeper.h"
#include "Flag.h"
#include "ShotUpdate.h"

/* local interface headers */
#include "BaseLocalPlayer.h"
#include "ShotStrategy.h"
#include "SceneDatabase.h"

class ShotStrategy;

class ShotPath {
  public:
    virtual		~ShotPath();

    bool		isExpiring() const;
    bool		isExpired() const;
    bool		isReloaded() const;
    const PlayerId&	getPlayer() const;
    uint16_t		getShotId() const;
    FlagType*		getFlag() const;
    float		getLifetime() const;
    float		getReloadTime() const;
    const TimeKeeper&	getStartTime() const;
    const TimeKeeper&	getCurrentTime() const;
    const float*	getPosition() const;
    const float*	getVelocity() const;

    float		checkHit(const BaseLocalPlayer*, float position[3]) const;
    void		setExpiring();
    void		setExpired();
    bool		isStoppedByHit() const;
    void		boostReloadTime(float dt);

    void		addShot(SceneDatabase*, bool colorblind);

    void		radarRender() const;
    FiringInfo&		getFiringInfo();
    TeamColor		getTeam() const;
  protected:
			ShotPath(const FiringInfo&);
    void		updateShot(float dt);
    const ShotStrategy*	getStrategy() const;
    ShotStrategy*	getStrategy();

    friend class ShotStrategy;
    void		setReloadTime(float);
    void		setPosition(const float*);
    void		setVelocity(const float*);

  private:
    ShotStrategy*	strategy;		// strategy for moving shell
    FiringInfo		firingInfo;		// shell information
    float		reloadTime;		// time to reload
    TimeKeeper		startTime;		// time of firing
    TimeKeeper		currentTime;		// current time
    bool		expiring;		// shot has almost terminated
    bool		expired;		// shot has terminated
};

class LocalShotPath : public ShotPath {
  public:
			LocalShotPath(const FiringInfo&);
			~LocalShotPath();

    void		update(float dt);
};

class RemoteShotPath : public ShotPath {
  public:
			RemoteShotPath(const FiringInfo&);
			~RemoteShotPath();

    void		update(float dt);
    void		update(const ShotUpdate& shot,
				uint16_t code, const void* msg);
};

//
// ShotPath
//

inline bool		ShotPath::isExpiring() const
{
  return expiring;
}

inline bool		ShotPath::isExpired() const
{
  return expired;
}

inline bool		ShotPath::isReloaded() const
{
  return (currentTime - startTime >= reloadTime);
}

inline const PlayerId&	ShotPath::getPlayer() const
{
  return firingInfo.shot.player;
}

inline uint16_t		ShotPath::getShotId() const
{
  return firingInfo.shot.id;
}

inline FlagType*	ShotPath::getFlag() const
{
  return firingInfo.flagType;
}

inline float		ShotPath::getLifetime() const
{
  return firingInfo.lifetime;
}

inline float		ShotPath::getReloadTime() const
{
  return reloadTime;
}

inline const TimeKeeper	&ShotPath::getStartTime() const
{
  return startTime;
}

inline const TimeKeeper	&ShotPath::getCurrentTime() const
{
  return currentTime;
}

inline const float*	ShotPath::getPosition() const
{
  return firingInfo.shot.pos;
}

inline const float*	ShotPath::getVelocity() const
{
  return firingInfo.shot.vel;
}

inline FiringInfo&	ShotPath::getFiringInfo()
{
  return firingInfo;
}

inline	TeamColor	ShotPath::getTeam() const
{
  return firingInfo.shot.team;
}

inline const ShotStrategy*	ShotPath::getStrategy() const
{
  return strategy;
}

inline ShotStrategy*	ShotPath::getStrategy()
{
  return strategy;
}

#endif /* __SHOTPATH_H__ */

// Local Variables: ***
// mode: C++ ***
// tab-width: 8 ***
// c-basic-offset: 2 ***
// indent-tabs-mode: t ***
// End: ***
// ex: shiftwidth=2 tabstop=8
