/// BulletML s
/**
 * gF
 * BulletMLRunner pĂ̏z֐B
 */

#ifndef BULLETRUNNER_H_
#define BULLETRUNNER_H_

#include "bulletmltree.h"
#include "bulletmlcommon.h"

#include <vector>
#include <boost/smart_ptr.hpp>

class BulletMLParser;
class BulletMLNode;
class BulletMLRunnerImpl;

typedef std::vector<double> BulletMLParameter;

/// BulletMLRunner ԓ`BɎgpNX
class BulletMLState {
public:
	DECLSPEC BulletMLState(BulletMLParser* bulletml,
						   const std::vector<BulletMLNode*>& node,
						   boost::shared_ptr<BulletMLParameter> para)
		: bulletml_(bulletml), node_(node.begin(), node.end()), para_(para) {}

	DECLSPEC BulletMLParser* getBulletML() { return bulletml_; }
	DECLSPEC const std::vector<BulletMLNode*>& getNode() const { return node_; }
	DECLSPEC boost::shared_ptr<BulletMLParameter> getParameter() { return para_; }

private:
	BulletMLParser* bulletml_;
	std::vector<BulletMLNode*> node_;
	boost::shared_ptr<BulletMLParameter> para_;

};

/// BulletML sNX
/**
 * <pre>
 * gB
 *  1. pāABullet ۂɓNXB
 *  2. z֐SĎB
 *  3. KvȂAchangeDirection Ȃǂ̂߂ɕKvȉz֐B
 *  4. ̃NX̃IuWFNgɑ΂āAcom_->run(); ȂǂƂB
 * </pre>
 */

class BulletMLRunner {
public:
	DECLSPEC explicit BulletMLRunner(BulletMLParser* bulletml);
    DECLSPEC explicit BulletMLRunner(BulletMLState* state);
    DECLSPEC virtual ~BulletMLRunner();

	/// s
    DECLSPEC void run();

public:
	/// sIĂ邩ǂ
	DECLSPEC bool isEnd() const;

public:
	// ----- ΎȂ΂ȂȂ֐Q̎n܂ -----
	//@{
	/// ̒e̊px߂
	/**
	 * @return pxxPʂŁA 0 ŎvŕԂ
	 */
	DECLSPEC virtual double getBulletDirection() =0;
	/// ̒e玩@_px߂
	/**
	 * @return pxxPʂŁA 0 ŎvŕԂ
	 */
	DECLSPEC virtual double getAimDirection() =0;
	/// ̒ȇx߂
	DECLSPEC virtual double getBulletSpeed() =0;
	/// ftHg̑x߂
	DECLSPEC virtual double getDefaultSpeed() =0;
	/// N߂
	/**
	 * @return 0  1 ܂ł̎
	 */
	DECLSPEC virtual double getRank() =0;
	/// action Ȃe
	DECLSPEC virtual void createSimpleBullet(double direction, double speed) =0;
	/// action e
	/**
	 * @param state
	 * Ve BulletMLRunner ̃RXgN^ɓnƁB
	 * nȂ̂ł΁Adelete ŉȂ΂ȂȂB
	 */
	DECLSPEC virtual void createBullet(BulletMLState* state,
									   double direction, double speed) =0;
	/// e̊ƂȂ^[̒lԂAʏ̓t[
	/**
	 * @return
	 * Q[Ƃ̊ŃI[_[͕ύXč\܂񂪁A
	 * ͋܂B
	 * xml f[^ŁAwait  term ̃I[_[ĂΖ肠܂B
	 */
	DECLSPEC virtual int getTurn() =0;
	/// 
	DECLSPEC virtual void doVanish() =0;
	//@}
	// ----- ΎȂ΂ȂȂ֐Q̏I -----

	// ----- KvΎ֐Q̎n܂ -----
   	//@{
	/// e̕w肵ɕύX
	DECLSPEC virtual void doChangeDirection(double) {}
	/// ȇxw肵lɕύX
	DECLSPEC virtual void doChangeSpeed(double) {}
	/// accel ɑ΂C^[tFCX
	/**
	 * @todo
	 * horizontal, vertical  type ͖łB
	 * ǂ absolute ɂȂĂ܂܂B
	 */
	DECLSPEC virtual void doAccelX(double) {}
	/// accel ɑ΂C^[tFCX
	/**
	 * @todo
	 * horizontal, vertical  type ͖łB
	 * ǂ absolute ɂȂĂ܂܂B
	 */
	DECLSPEC virtual void doAccelY(double) {}
	/// ȇ X Ԃ܂
	/**
	 * accel gꍇ̓I[o[Chĉ
 	 */
	DECLSPEC virtual double getBulletSpeedX() { return 0; }
	/// ȇ Y Ԃ܂
	/**
	 * accel gꍇ̓I[o[Chĉ
 	 */
	DECLSPEC virtual double getBulletSpeedY() { return 0; }
    //@}
	// ----- KvΎ֐Q̏I -----

	/// Ԃ
	/**
	 * Ă̂ƂAftHgł std::rand p܂B
	 */
	DECLSPEC virtual double getRand() { return (double)rand() / RAND_MAX; }

private:
	/// BulletMLRunnerImpl I[o[ChꍇAI[o[Ch
	DECLSPEC virtual BulletMLRunnerImpl* makeImpl(BulletMLState* state);

protected:
	std::vector<BulletMLRunnerImpl*> impl_;

};

#endif // ! BULLETRUNNER_H_

