#pragma once
#include "dojo/dojo.h"
#include "PullPoint.h"
#include "Configuration.h"
#include "Move.h"
#include <string>
#include <iostream>
#include <map>

using namespace dojo;
class Demo;

class Marionette : public StickFigure {

private:

	Demo *applet;
	Array<PullPoint*> strings; // the pull points
	Array<Configuration*> configs;
	int ppIndex;
	int configIndex;

	Array<Move*> allMoves;
	Array<char* > allNames;
	Move* currentMove;
	int selectedPose;
	float elapsedTime;
	float downTime, recovery, strike;

	bool doMove;
	bool touchingGround, wasTouchingGround;
	int playerNumber;
	int maxMoveId;
	Marionette *opponent;
	Configuration* defaultStance;

	typedef std::map<int, Move*> mmap;
	typedef std::map<std::string, int> attack_value_map;
	typedef mmap::iterator p_iter;
	mmap moveMap;
	attack_value_map valueMap;

	Marionette(const std::string& name, int pnum, Demo* d);

public:

	void setOpponent(Marionette* opp);
	virtual ~Marionette(void);

    static EntityRef create(const std::string& name, int pnum, Demo* d) {
		return EntityRef(new Marionette(name, pnum, d));
    }

	virtual void onSimulation(G3D::SimTime ts);

	void initPullPoints(const CoordinateFrame& wsC);
	void setFrame(const CoordinateFrame& wsC);

	PullPoint* nextPullPoint(void);
	void setPullPoint(int index);

	Array<char* > loadMoves(int pid);
	
	void setPose();

	void playMove();
	void playMove(int index);
	int moveCount(void);
	bool isMoving(void);
	Move* getMove(int index);

	void applyConfiguration(Configuration* pose);
	void setDefaultConfiguration(Configuration* pose);
	void setConfiguration();

	void setMoveTarget(Entity::Part* target);
	void setAttackLimb(PullPoint* pullpoint);

	Move* selectMove(int index);
	Move* getCurrentMove(void);
	Configuration* selectConfiguration(int index);

	Array<PullPoint*> getStrings(void);
	Entity::Part* hackPart(const std::string &partName);
	void release(bool fall);

	void stopMoving(void);

	virtual bool onCollision(const std::string &myPart, const dojo::EntityRef &other, const std::string &otherPart, const Vector3 &wsLocation);

	void turnTo(CoordinateFrame cf);
	bool isAttacking(void);

	Configuration* getDefaultConfiguration(void);
	Array<std::string> getPartNames(void);
	void resetStrike(void);
	Move* selectMoveById(int id);
	void clearMoves(void);
	int attackValue(std::string limbname);
};
