#ifndef GAME_BOT_HEADER
#define GAME_BOT_HEADER

#include <cstdio>
#include "String.h"
#include "Sockets.h"
#include "Commands.h"
#include "Map.h"
#include "Stack.h"
#include "Poliz.h"
#include "List.h"

class Connection
{
public:
	class ConnectError{};

private:
	ClientSocket socket;
	String buffer;

	String getLine();

public:
	void Connect(const String host, const unsigned port) const;
	Answer WaitAnswer(const Answer::Type type, const String name = "");
	Answer NextAnswer();
	void SendCommand(const String command) const;
};

class GameStruct
{
public:
	virtual void Receive(Connection &connection) = 0;
};

class Market: public GameStruct
{
private:
	unsigned rawCount;
	unsigned rawPrice;
	unsigned prodCount;
	unsigned prodPrice;

public:
	inline unsigned GetRawCount() const {return rawCount;}
	inline unsigned GetRawPrice() const {return rawPrice;}
	inline unsigned GetProdCount() const {return prodCount;}
	inline unsigned GetProdPrice() const {return prodPrice;}

	void Receive(Connection &connection);
};

class Players: public GameStruct
{
private:
	unsigned count;

public:
	inline unsigned GetCount() const {return count;}

	void Receive(Connection &connection);
};

class GameBot
{
friend class Interpreter;
public:
	enum GameResult {gr_win, gr_lose, gr_draw};
	class ConnectError{};

private:
	String name;
	Connection connection;
	Market market;
	Players players;

	void buy(const unsigned count, const unsigned price);
	void sell(const unsigned count, const unsigned price);
	void prod(const unsigned count);
	void say(const String &what);
	bool turn(GameResult *result = 0);

public:
	GameBot(const String name);

	void Connect(const String host, const unsigned port) const;
	void Join(const unsigned gameID = 0);
	void Create(const unsigned players = 2);
	GameResult Play(FILE *script);
};

class Interpreter: private ScriptFunctions
{
private:
	VarsTable *table;
	PolizStack *stack;
	List<PolizElement*> poliz;
	GameBot *bot;
	
	List<PolizElement*>::Iterator current;
	
	virtual void sell(int count);
	virtual void buy(int count);
	virtual void prod(int count);
	virtual void say(int count);
	
public:
	Interpreter(GameBot *bot);
	~Interpreter();
	
	void Append(PolizElement *element);	
	void Clear();
	
	void Evaluate();
	
	class InvalidParams{};
};

#endif
