#ifndef __ASCRIPTSHELL_H__
#define __ASCRIPTSHELL_H__

#include <wx/wx.h>
#include <wx/textctrl.h>
#include <ascript.h>
#include <deque>

//-----------------------------------------------------------------------------
// AScriptShell
//-----------------------------------------------------------------------------
class AScriptShell : public wxTextCtrl {
private:
	typedef std::deque<wxString> LineHistory;
	class StreamEx : public AScript::Stream {
	private:
		wxString _str;
		AScriptShell *_pAScriptShell;
	public:
		StreamEx(AScript::Signal sig, AScriptShell *pAScriptShell);
		virtual const char *GetName() const;
		virtual void DoPutChar(AScript::Signal sig, char ch);
		virtual void FlushConsole();
	};
	class EvalLineThread : public wxThread {
	private:
		AScriptShell *_pAScriptShell;
		wxString _str;
	public:
		EvalLineThread(AScriptShell *pAScriptShell, const wxString &str);
		virtual ExitCode Entry();
	};
	class EvalFileThread : public wxThread {
	private:
		AScriptShell *_pAScriptShell;
		wxString _fileName;
	public:
		EvalFileThread(AScriptShell *pAScriptShell, const wxString &fileName);
		virtual ExitCode Entry();
	};
private:
	long _posLineTop;
	LineHistory _lineHistory;
	LineHistory::reverse_iterator _pLineHistory;
	StreamEx _console;
	AScript::EnvironmentRoot _env;
	AScript::Signal _sig;
	AScript::Parser _parser;
	bool _threadRunningFlag;
	bool _scrollViewFlag;
public:
	AScriptShell(wxWindow *pParent, wxWindowID id, long style);
	virtual ~AScriptShell();
	inline void MarkLineTop() { _posLineTop = GetLastPosition(); }
	inline long GetLineTopPoint() const { return _posLineTop; }
	inline AScript::Environment &GetEnvironment() { return _env; }
	inline AScript::Signal &GetSignal() { return _sig; }
	inline AScript::Parser &GetParser() { return _parser; }
	inline bool IsScrollView() const { return _scrollViewFlag; }
	bool IsThreadRunning() const { return _threadRunningFlag; }
	void UpdateFont();
	void UpdateColor();
	void EvalFile(const wxString &fileName);
	void EnterScrollView();
	void LeaveScrollView();
	void RunThread(wxThread *pThread);
	void NotifyEndOfThread();
private:
	DECLARE_EVENT_TABLE()
	void OnKeyDown(wxKeyEvent &event);
};

#endif
