/* Mednafen - Multi-system Emulator
 *
 * 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; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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 for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include "main.h"
#include "logdebugger.h"
#include "debugger.h"
#include "prompt.h"

#include <vector>

typedef struct
{
 char *type;
 char *text;
} LogEntry;

static bool IsActive = FALSE;
static bool LoggingActive = FALSE;
static std::vector<LogEntry> DeathLog;
static uint32 LogScroll = 0;

static void TheLogger(const char *type, const char *text)
{
 LogEntry nle;

 nle.type = strdup(type);
 nle.text = strdup(text);

 DeathLog.push_back(nle);

 if((DeathLog.size() - LogScroll) == 33)
  LogScroll++;
}


// Call this function from either thread.
void LogDebugger_SetActive(bool newia)
{
 if(CurGame->Debugger)
 {
  LockGameMutex(1);

  IsActive = newia;
  if(!newia)
  {
   //InEditMode = FALSE;
   //LowNib = FALSE;
  }
  LockGameMutex(0);
 }
}

#define MK_COLOR_A(r,g,b,a) ( ((a)<<surface->format->Ashift) | ((r)<<surface->format->Rshift) | ((g) << surface->format->Gshift) | ((b) << surface->format->Bshift))

// Call this function from the main thread
void LogDebugger_Draw(SDL_Surface *surface, const SDL_Rect *rect, const SDL_Rect *screen_rect)
{
 if(!IsActive) return;

 uint32 * pixels = (uint32 *)surface->pixels;
 uint32 pitch32 = surface->pitch >> 2;
 char logmessage[256];

 snprintf(logmessage, 256, "%s (%d messages)", LoggingActive ? (UTF8*)"Logging Enabled" : (UTF8*)"Logging Disabled", (int)DeathLog.size());
 DrawTextTrans(pixels, surface->pitch, rect->w, (UTF8*)logmessage, MK_COLOR_A(0x20, 0xFF, 0x20, 0xFF), 1, MDFN_FONT_6x13_12x13);
 pixels += 13 * pitch32;

 for(uint32 i = LogScroll; i < (LogScroll + 32) && i < DeathLog.size(); i++)
 {
  uint32 typelen;
  static const uint32 lifecolors[4] = { MK_COLOR_A(0xe0, 0xd0, 0xd0, 0xFF), MK_COLOR_A(0xd0, 0xe0, 0xd0, 0xFF),
					MK_COLOR_A(0xd0, 0xd0, 0xEF, 0xFF), MK_COLOR_A(0xd4, 0xd4, 0xd4, 0xFF) 
				      };
  char tmpbuf[64];

  snprintf(tmpbuf, 64, "%d", i);
  typelen = DrawTextTrans(pixels, surface->pitch, rect->w, (UTF8*)tmpbuf, MK_COLOR_A(0x80, 0x80, 0xD0, 0xFF), FALSE, MDFN_FONT_5x7);
  typelen += 1;

  typelen += DrawTextTrans(pixels + typelen, surface->pitch, rect->w - typelen, (UTF8*)DeathLog[i].type, MK_COLOR_A(0xFF, 0x40, 0x40, 0xFF), FALSE, MDFN_FONT_6x13_12x13);
  typelen += 5;
  DrawTextTrans(pixels + typelen, surface->pitch, rect->w - typelen, (UTF8*)DeathLog[i].text, lifecolors[i & 3], FALSE, MDFN_FONT_6x13_12x13);
  pixels += pitch32 * 13;
 }
}

static void ChangePos(int64 delta)
{
 int64 NewScroll = (int64)LogScroll + delta;

 if(NewScroll > ((int64)DeathLog.size() - 32))
 {
  NewScroll = (int64)DeathLog.size() - 32;
 }

 if(NewScroll < 0) 
 {
  NewScroll = 0;
 }

 LogScroll = NewScroll;
}

// Call this from the main thread
int LogDebugger_Event(const SDL_Event *event)
{
 switch(event->type)
 {
  case SDL_KEYDOWN:
	switch(event->key.keysym.sym)
	{
	 default: break;

         case SDLK_MINUS: Debugger_ModOpacity(-8);
                          break;
         case SDLK_EQUALS: Debugger_ModOpacity(8);
                           break;


	 case SDLK_HOME: LogScroll = 0; break;
	 case SDLK_END: ChangePos(1 << 30); break;

	 case SDLK_UP: ChangePos(-1); break;
	 case SDLK_DOWN: ChangePos(1); break;
	 case SDLK_PAGEUP: ChangePos(-32); break;
	 case SDLK_PAGEDOWN: ChangePos(32); break;

	 case SDLK_t:
		     LoggingActive = !LoggingActive;
		     if(CurGame->Debugger->SetLogFunc)
			CurGame->Debugger->SetLogFunc(LoggingActive ? TheLogger : NULL);
		     break;


	}
	break;

 }
 return(1);
}

