/*
Copyright (C) 1997-2001 Id Software, Inc.

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 <string.h>
#include "ui_local.h"

/*
=============================================================================

DEMOS MENU

=============================================================================
*/
void Demos_MenuInit( void );

static menuframework_s	s_demos_menu;


//=====================================================================
// PATH
//=====================================================================
// the current working directory
// init with demos
// each time we go in a new folder we append /name to cwd
// when user press backspace we go back one folder:
//   ie: we reverse search for a / and replace by a \0
char cwd[MAX_QPATH]; 

//=====================================================================
// Items list
//=====================================================================

//#define MAX_MENU_LIST_ITEMS 15
static int MAX_MENU_LIST_ITEMS = 15;

m_itemslisthead_t demosItemsList;

void M_Demos_PreviousFolder(void)
{
	// go back to previous folder
	char *slash;

	slash=strrchr(cwd, '/');

	if(slash!=NULL)
	{
		// erase prev folder
		*slash='\0';
		// rebuild list
		Demos_MenuInit();
	}
}
//==================
//M_Demos_CreateFolderList
//==================
void M_Demos_CreateFolderList( void )
{
	char	*s;
	char	buffer[8*1024];
	int		numfolders;
	int		length;
	int		i;
	char	foldername[MAX_QPATH];

	if( (numfolders = trap_FS_GetFileList( cwd, "/", buffer, sizeof(buffer) )) == 0 )
		return;

	s = buffer;
	length = 0;
	for ( i = 0; i < numfolders; i++, s += length+1 )
	{
		length = strlen( s );
		Q_strncpyz( foldername, s, sizeof(foldername) );
		foldername[length-1]='\0'; // to remove the ending slash
		UI_AddItemToScrollList( &demosItemsList, foldername, NULL );
	}
}

//==================
//M_Demos_CreateDemosList
//==================
void M_Demos_CreateDemosList( void )
{
	char	*s;
	char	buffer[8*1024];
	int		numdemos;
	int		length;
	int		i;
	char	demoname[MAX_QPATH];

	if( (numdemos = trap_FS_GetFileList( cwd, va(".wd%d",PROTOCOL_VERSION), buffer, sizeof(buffer) )) == 0 )
		return;

	s = buffer;
	length = 0;
	for ( i = 0; i < numdemos; i++, s += length+1 )
	{
		length = strlen( s );
		Q_strncpyz( demoname, s, sizeof(demoname) );
		demoname[length]='\0';
		UI_AddItemToScrollList( &demosItemsList, demoname, NULL );
	}
}

//==================
//M_Demos_CreateItemList
//==================
void M_Demos_CreateItemList( void )
{
	// first free the current list
	UI_FreeScrollItemList( &demosItemsList );

	// get all the folders
	M_Demos_CreateFolderList();

	// get all the demos
	M_Demos_CreateDemosList();
}


//=====================================================================
// Buttons & actions
//=====================================================================
#define	NO_ITEM_STRING	""
static int	scrollbar_curvalue = 0;

//==================
//M_Connect_UpdateScrollbar
//==================
void M_Demos_UpdateScrollbar( menucommon_t *menuitem ) 
{
	scrollbar_curvalue = menuitem->curvalue;
	menuitem->maxvalue = max( 0, demosItemsList.numItems - MAX_MENU_LIST_ITEMS );
}

//==================
//M_Demo_Playdemo
//==================
void M_Demo_Playdemo( menucommon_t *menuitem ) 
{
	char	buffer[MAX_STRING_CHARS];
	m_listitem_t *item;

	menuitem->localdata[1] = menuitem->localdata[0] + scrollbar_curvalue;
	item = UI_FindItemInScrollListWithId( &demosItemsList, menuitem->localdata[1] );
	if( item ) 
	{
		if( item->name)
		{
			// can be a demos or a folder
			if(strstr(item->name,va(".wd%d",PROTOCOL_VERSION))!=NULL)
			{
				// it is a demos
				//cwd is "demos/path"
				// we need to remove demos
				char *slash=strchr(cwd,'/');
				if(slash==NULL)
					Q_snprintfz( buffer, sizeof(buffer), "demo \"%s\"\n", item->name );
				else
				{
					slash++; // skip the slash
					trap_Print(va("demo %s/%s\n", slash, item->name));
					Q_snprintfz( buffer, sizeof(buffer), va("demo \"%s/%s\"\n", slash,item->name) );
				}
				trap_Cmd_ExecuteText( EXEC_APPEND, buffer );
			}
			else
			{
				// it is a folder
				int len=strlen(item->name)+1;

				// sanity
				if(strlen(cwd)+len>MAX_QPATH)
				{
					UI_Printf("Max sub folder limit reached\n");
					return;
				}

				// add /name to cwd
				strcat(cwd, va("/%s", item->name));

				// rebuild the lists
				Demos_MenuInit();
			}
		}
	}
}

//==================
//M_Demo_DemoButton
//==================
void M_Demo_UpdateButton( menucommon_t *menuitem ) 
{
	m_listitem_t *item;

	menuitem->localdata[1] = menuitem->localdata[0] + scrollbar_curvalue;
	item = UI_FindItemInScrollListWithId( &demosItemsList, menuitem->localdata[1] );
	if( item ) {
		Q_snprintfz(menuitem->title, MAX_STRING_CHARS, item->name);
	} else
		Q_snprintfz(menuitem->title, MAX_STRING_CHARS, NO_ITEM_STRING);
}

//==================
//Demos_MenuInit
//==================
void Demos_MenuInit( void )
{
	char path[MAX_QPATH];

	menucommon_t *menuitem;
	int i;
	int y = 0;
	int yoffset;
	int scrollwindow_width, scrollwindow_height;

	yoffset = UI_SCALED_HEIGHT(56); // left space for the logo

	// scroll window width
	if( uis.vidWidth < 800 )
		scrollwindow_width = uis.vidWidth * 0.85;
	else if( uis.vidWidth < 1024 )
		scrollwindow_width = uis.vidWidth * 0.75;
	else
		scrollwindow_width = uis.vidWidth * 0.65;

	s_demos_menu.x = uis.vidWidth / 2;
	s_demos_menu.nitems = 0;

	// build the list folder and demos
	M_Demos_CreateItemList();

	// title
	menuitem = UI_InitMenuItem( "m_demos_title1", "DEMOS", 0, y+yoffset, MTYPE_SEPARATOR, ALIGN_CENTER_TOP, uis.fontSystemBig, NULL );
	Menu_AddItem( &s_demos_menu, menuitem );
	yoffset += trap_SCR_strHeight( menuitem->font );

	// current folder
	Q_snprintfz( path, sizeof(path), "%sCurrent folder: %s%s", S_COLOR_YELLOW, S_COLOR_WHITE, cwd );
	menuitem = UI_InitMenuItem("m_demos_folder", path, -(scrollwindow_width/2), y+yoffset, MTYPE_SEPARATOR, ALIGN_LEFT_TOP, uis.fontSystemSmall, NULL );
	Menu_AddItem( &s_demos_menu, menuitem );
	yoffset += trap_SCR_strHeight( menuitem->font );

	// Back button (back in demo browser)
	menuitem = UI_InitMenuItem( "m_demo_button_back", "Directory up", -(scrollwindow_width/2), y+yoffset, MTYPE_ACTION, ALIGN_LEFT_TOP, uis.fontSystemSmall, M_Demos_PreviousFolder );
	menuitem->statusbar = "press for previous folder";
	Menu_AddItem( &s_demos_menu, menuitem );
	yoffset += trap_SCR_strHeight( menuitem->font );

	yoffset += trap_SCR_strHeight( menuitem->font );

	// scrollbar

	scrollwindow_height = uis.vidHeight - ( yoffset + ( 2 * trap_SCR_strHeight( uis.fontSystemBig ) ) );
	MAX_MENU_LIST_ITEMS = ( scrollwindow_height / trap_SCR_strHeight( uis.fontSystemSmall ) ) - 6; // 6 lines left for back button
	if( MAX_MENU_LIST_ITEMS < 5 ) MAX_MENU_LIST_ITEMS = 5;

	menuitem = UI_InitMenuItem( "m_demos_scrollbar", NULL, -((scrollwindow_width*0.5)+16), y+yoffset, MTYPE_SCROLLBAR, ALIGN_CENTER_TOP, uis.fontSystemSmall, M_Demos_UpdateScrollbar );
	UI_SetupScrollbar( menuitem, MAX_MENU_LIST_ITEMS-1, 0, 0, 0 );
	Menu_AddItem( &s_demos_menu, menuitem );
	
	// demos/folder buttons
	for( i = 0; i < MAX_MENU_LIST_ITEMS; i++ )
	{
		menuitem = UI_InitMenuItem( va("m_demos_button_%i", i), NO_ITEM_STRING, -(scrollwindow_width*0.5), y+yoffset, MTYPE_ACTION, ALIGN_LEFT_TOP, uis.fontSystemSmall, M_Demo_Playdemo );
		menuitem->statusbar = "press ENTER to play demos/enter folder, BACKSPACE for previous folder";
		menuitem->ownerdraw = M_Demo_UpdateButton;
		menuitem->localdata[0] = i; // line in the window
		menuitem->localdata[1] = i;  // line in list
		menuitem->width = scrollwindow_width; // adjust strings to this width
		Menu_AddItem( &s_demos_menu, menuitem );

		// create an associated picture to the items to act as window background
		menuitem->pict.shader = uis.whiteShader;
		menuitem->pict.shaderHigh = uis.whiteShader;
		Vector4Copy( colorWhite, menuitem->pict.colorHigh );
		Vector4Copy( ( i & 1 )?colorDkGrey:colorMdGrey, menuitem->pict.color );
		menuitem->pict.color[3] = menuitem->pict.colorHigh[3] = 0.65f;
		menuitem->pict.yoffset = 0;
		menuitem->pict.xoffset = 0;
		menuitem->pict.width = scrollwindow_width;
		menuitem->pict.height = trap_SCR_strHeight( menuitem->font );

		yoffset += trap_SCR_strHeight( menuitem->font );
	}

	yoffset += trap_SCR_strHeight( menuitem->font );

	// back (to previous menu)
	menuitem = UI_InitMenuItem( "m_demos_back", "back", 0, y+yoffset, MTYPE_ACTION, ALIGN_CENTER_TOP, uis.fontSystemBig, M_genericBackFunc );
	Menu_AddItem( &s_demos_menu, menuitem );
	yoffset += trap_SCR_strHeight( menuitem->font );

	Menu_Center( &s_demos_menu );
	Menu_Init( &s_demos_menu );
}

void Demos_MenuDraw(void)
{
	Menu_Draw( &s_demos_menu );
}

const char *Demos_MenuKey( int key )
{
	menucommon_t *item;

	item = Menu_ItemAtCursor( &s_demos_menu );

	if ( key == K_ESCAPE || ( (key == K_MOUSE2) && (item->type != MTYPE_SPINCONTROL) &&
		(item->type != MTYPE_SLIDER)) )
	{
		UI_FreeScrollItemList( &demosItemsList );
	}
	else if( key == K_BACKSPACE )
	{
		M_Demos_PreviousFolder();
	}
	return Default_MenuKey( &s_demos_menu, key );
}

const char *Demos_MenuCharEvent( int key )
{
	return Default_MenuCharEvent( &s_demos_menu, key );
}

void M_Menu_Demos_f( void )
{
	// init current working directory
	memset(cwd, '\0', sizeof(cwd));
	Q_snprintfz(cwd, sizeof(cwd), "demos");

	// lets go
	Demos_MenuInit();
	M_PushMenu( &s_demos_menu, Demos_MenuDraw, Demos_MenuKey, Demos_MenuCharEvent );
}
