#if defined(__FLAT__)
#include <common/console.hpp>
#include <common/coord.hpp>
#include <common/smrect.hpp>

Console::Console()
: mhConsole(0), mHasConsole(FALSE), mIsSystemConsole(TRUE)
{
  mhConsole=::GetStdHandle(STD_OUTPUT_HANDLE);
	if(mhConsole)mHasConsole=true;
}

Console::Console(ConsoleType consoleType,bool forceCreate)
: mhConsole(0), mHasConsole(FALSE), mIsSystemConsole(FALSE)
{
	if(!mhConsole&&!::AllocConsole())
	{
	  if(!forceCreate)return;
		::FreeConsole();
		if(!AllocConsole())return;
	}
	mHasConsole=TRUE;
	if(0==(mhConsole=::CreateConsoleScreenBuffer(consoleType,FILE_SHARE_READ|FILE_SHARE_WRITE,(LPSECURITY_ATTRIBUTES)0,CONSOLE_TEXTMODE_BUFFER,0)))
	{
		::FreeConsole();
		mHasConsole=FALSE;
		return;
	}
	::SetConsoleActiveScreenBuffer(mhConsole);
	::GetConsoleScreenBufferInfo(mhConsole,&((CONSOLE_SCREEN_BUFFER_INFO&)mConsoleScreenBufferInfo));
  setConsoleMode(ENABLE_LINE_INPUT|ENABLE_ECHO_INPUT);
}

Console::~Console()
{
  if(mIsSystemConsole)return;
  if(mhConsole){::CloseHandle(mhConsole);mhConsole=0;}
  if(mHasConsole){::FreeConsole();mHasConsole=FALSE;}
}

Console::operator HANDLE(void)
{
  return mhConsole;
}

WORD Console::read(void)
{
	String consoleString;
	return read(consoleString);
}

WORD Console::read(String &consoleString)
{
	String consoleInputString;
	DWORD bytesRead;
	HANDLE mhConsoleInput;

	if(!mhConsole)return FALSE;
	if(!::ReadConsole(::GetStdHandle(STD_INPUT_HANDLE),(LPSTR)consoleInputString,String::MaxString-1,&bytesRead,0))return FALSE;
	consoleString=consoleInputString;
	return TRUE;
}

BOOL Console::readBufferLine(int row,String &lineString)
{
	Coord coord(0,row);
	DWORD bytesRead;

  if(!mhConsole)return FALSE;
  const ConsoleScreenBufferInfo &consoleScreenBufferInfo=getConsoleScreenBufferInfo();	  
	lineString.reserve(consoleScreenBufferInfo.maxWinRect().x());
	return ::ReadConsoleOutputCharacter(*this,lineString,consoleScreenBufferInfo.maxWinRect().x(),(COORD&)coord,&bytesRead);
}

WORD Console::fillConsoleOutputAttribute(WORD colorAttr,DWORD numChars,const Coord &writeCoord)
{
  DWORD cellsWritten;

  if(!mhConsole)return FALSE;
  return ::FillConsoleOutputAttribute(mhConsole,colorAttr,numChars,(COORD&)(Coord&)writeCoord,&cellsWritten);  
}

WORD Console::fillConsoleOutputCharacter(TCHAR outChar,DWORD nLength,const Coord &writeCoord)
{
  DWORD cellsWritten;

  if(!mhConsole)return FALSE;
  return ::FillConsoleOutputCharacter(mhConsole,outChar,nLength,(COORD&)(Coord&)writeCoord,&cellsWritten);
}
#endif
