// Copyright (C) 2003-2008 Dolphin Project.

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License 2.0 for more details.

// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/

// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/


//////////////////////////////////////////////////////////////////////////////////////////
// Includes
// -------------
#include <string> // System: To be able to add strings with "+"
#include <stdio.h>
#ifdef _WIN32
	#include <windows.h>
#endif

#include "Common.h"
#include "ConsoleWindow.h" // Common
///////////////////////////


//////////////////////////////////////////////////////////////////////////////////////////
// Declarations and definitions
// -------------

namespace Console
{

// Create handles
#ifdef _WIN32
	FILE* __fStdOut = NULL;
	HANDLE __hStdOut = NULL;
#endif

//////////////////////////////


//////////////////////////////////////////////////////////////////////////////////////////
/* Start console window - width and height is the size of console window, if you enable
   File the output will also be written to this file. */
// -------------
void Open(int Width, int Height, char * Name, bool File)
{
#ifdef _WIN32
	// Open the console window and create the window handle for GetStdHandle()
	AllocConsole();

	// Save the window handle that AllocConsole() created
	__hStdOut = GetStdHandle(STD_OUTPUT_HANDLE);

	// Set the console window title
	SetConsoleTitle(Name);

	// Set the total letter space
	COORD co = {Width, Height};
	SetConsoleScreenBufferSize(__hStdOut, co);

	/* Set the window size in number of letters. The height is hardcoded here because it can
	   be changed with MoveWindow() later */
	SMALL_RECT coo = {0,0, (Width - 1),50}; // Top, left, right, bottom
	SetConsoleWindowInfo(__hStdOut, TRUE, &coo);

	// -----------------------------------------
	// Create a file and a file handle if File is enabled and we don't already have a file handle
	// -------------
	if(File && !__fStdOut)
	{
		// Edit the log file name
		std::string FileEnding = ".log";
		std::string FileName = Name;	
		std::string FullFilename = (FileName + FileEnding);

		// Open the file handle
		__fStdOut = fopen(FullFilename.c_str(), "w");
	}
	// ---------------
#endif
}
//////////////////////////////


//////////////////////////////////////////////////////////////////////////////////////////
/* Close the console window and close the eventual file handle */
// -------------
void Close()
{
#ifdef _WIN32
	FreeConsole(); // Close the console window
	if(__fStdOut) fclose(__fStdOut); // Close the file handle
#endif
}
//////////////////////////////


//////////////////////////////////////////////////////////////////////////////////////////
// Print to screen and file
// -------------
int Print(const char *fmt, ...)
{
#if defined(_WIN32)
	if(__hStdOut)
	{
		char s[1024*20]; // Warning, mind this value
		va_list argptr;
		int cnt; // To store the vsnprintf return message

		va_start(argptr, fmt);
		cnt = vsnprintf(s, 500, fmt, argptr);
		va_end(argptr);

		DWORD cCharsWritten; // We will get a value back here

		// ------------------------------------------
		// Write to console
		// ----------------
		if(__hStdOut)
		{
			WriteConsole(__hStdOut, s, (DWORD)strlen(s), &cCharsWritten, NULL);
		}

		// ----------------------------------------
		// Write to the file
		// ----------------
		if(__fStdOut)
		{
			fprintf(__fStdOut, s);
			fflush(__fStdOut); // Write file now, don't wait
		}

		return(cnt);
	}
	else
	{
		return 0;
	}
#else
	return 0;
#endif
}
/////////////////////////////


// =======================================================================================
// Clear console screen
// ---------------
void ClearScreen() 
{ 
#if defined(_WIN32)
	if(__hStdOut) // Check that we have a window handle
	{
		COORD coordScreen = { 0, 0 }; 
		DWORD cCharsWritten; 
		CONSOLE_SCREEN_BUFFER_INFO csbi; 
		DWORD dwConSize; 

		HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); 
	    
		GetConsoleScreenBufferInfo(hConsole, &csbi); 
		dwConSize = csbi.dwSize.X * csbi.dwSize.Y; 
		FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, 
			coordScreen, &cCharsWritten); 
		GetConsoleScreenBufferInfo(hConsole, &csbi); 
		FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, 
			coordScreen, &cCharsWritten); 
		SetConsoleCursorPosition(hConsole, coordScreen); 
	}
#endif
}
// =====================


// =======================================================================================
/* Get window handle of console window to be able to resize it. We use GetConsoleTitle() and
   FindWindow() to locate the console window handle. */
// ---------------
#if defined(_WIN32)
HWND GetHwnd(void)
{
   #define MY_BUFSIZE 1024 // Buffer size for console window titles
   HWND hwndFound;         // This is what is returned to the caller
   char pszNewWindowTitle[MY_BUFSIZE]; // Contains fabricated WindowTitle
   char pszOldWindowTitle[MY_BUFSIZE]; // Contains original WindowTitle

   // Fetch current window title.
   GetConsoleTitle(pszOldWindowTitle, MY_BUFSIZE);

   // Format a "unique" NewWindowTitle
   wsprintf(pszNewWindowTitle, "%d/%d", GetTickCount(), GetCurrentProcessId());

   // Change current window title
   SetConsoleTitle(pszNewWindowTitle);

   // Ensure window title has been updated
   Sleep(40);

   // Look for NewWindowTitle
   hwndFound = FindWindow(NULL, pszNewWindowTitle);

   // Restore original window title
   SetConsoleTitle(pszOldWindowTitle);

   return(hwndFound);
}
#endif // _WIN32
// =====================

} // namespace