<rml>
<head>
	<title>game</title>
	<link type="text/template" href="template.rml" />
	<link type="text/css" rel="stylesheet" href="css/serverlist.rcss" />
	<link type="text/css" rel="stylesheet" href="css/modal.rcss" />
	<script src="as/favorites.as" />
	<script>

	class SortedServer
	{
		uint index;
		uint players;
	}

	const String browserDataSourceName = 'serverbrowser_source';
	const String browserTableNameDefault = 'normal';

	const String gametypesDataSourceName = 'gametypes_source';
	const String gametypesTableName = 'list';

	bool isUpdating = false;
	bool isStopped = false;
	bool isGridHidden = false;

	const uint MAX_CHAINED_SERVERS = 10;
	const uint AUTO_UPDATE_TIMEOUT = 60*1000;

	uint lastModalUpdateId = 0;

	DataSource @browserDataSource;
	DataSource @gametypesDataSource;
	Element @navibar;
	Element @servergrid;
	Element @refreshbtn;
	Element @connectbtn;
	Element @favoritebtn;
	Element @serverblock;
	Element @progresstitle;
	Element @progresscounter;

	void onJoinLoad( Element @body, Event @ev )
	{
		String tmp;

		onTemplateLoad( body, ev );

		@navibar = body.getElementById( 'navibar' );
		@refreshbtn = body.getElementById( 'refresh-btn' );
		@connectbtn = body.getElementById( 'connect-btn' );
		@favoritebtn = body.getElementById( 'favorite-btn' );

		// set the source table for the datagrid

		@servergrid = body.getElementById( 'serverbrowser_datagrid' );
		@serverblock = body.getElementById( 'serverblock' );
		@progresstitle = body.getElementById( 'in-progress-title' );
		@progresscounter = body.getElementById( 'in-progress-counter' );

		ElementDataGrid @grid = servergrid;
		if( @grid == null ) {
			return;
		}

		window.setInterval( onJoinThink, 200 );

		@browserDataSource = getDataSource( browserDataSourceName );
		@gametypesDataSource = getDataSource( gametypesDataSourceName );

		grid.setDataSource( browserDataSourceName + ".normal" );

		Element @cleanname = null;
		float width = 0.0;
		for( int i = 0; i < int( grid.getNumColumns() ); i++ ) {
			if( grid.getFields( i )[0] == 'cleanname' ) {
				@cleanname = grid.getColumnHeader( i );
			} else {
				width += grid.getColumnHeader( i ).clientWidth();
			}
		}
		if( @cleanname != null ) {
			cleanname.setProp( 'width', String( servergrid.clientWidth() - width ) + 'px' );
		}

		// hide the infoblock as we haven't picked a server yet
		serverblock.css( 'display', 'none' );
		connectbtn.css( 'display', 'none' );
		favoritebtn.css( 'display', 'none' );

		isGridHidden = false;

		Favorites::init();
	}

	void onJoinShow( Element @body, Event @ev )
	{
		// start the update
		if( !serverBrowser.isUpdating()
			&& ( serverBrowser.getLastActiveTime() == 0/* || window.time > serverBrowser.getLastActiveTime() + AUTO_UPDATE_TIMEOUT*/ ) ) {
			serverBrowser.fullUpdate();
		}

		Element @container = body.getElementById( 'serverbrowser-container' );
		body.getElementById( 'serverbrowser_frame' ).css( 'height',
			(body.getElementById( 'leftside' ).clientHeight()
			- int( container.resolveProp( 'padding-top', container.clientHeight() ) )
			- int( container.resolveProp( 'padding-bottom', container.clientHeight() ) )
			) + 'px'
		);

		onTemplateShow( body, @ev );

		onJoinThink();

		updateBrowserVisibility();

		animationsOnShow( true );
	}

	void onJoinHide( Element @self, Event @ev )
	{
	}

	void onRefreshButtonClick( Element @self, Event @ev )
	{
		if( serverBrowser.isUpdating() ) {
			isStopped = true;
			serverBrowser.stopUpdate();
		} else {
			isStopped = false;
			serverBrowser.fullUpdate();
		}
		updateRefreshTitle();
		updateBrowserVisibility();
	}

	bool updateRefreshTitle()
	{
		if( @refreshbtn == null ) {
			return false;
		}

		// note: can't use getInnerRML here because of l10n
		String curAction = refreshbtn.getAttr( 'action', 'Refresh' );
		String newAction = serverBrowser.isUpdating() ? 'Stop' : 'Refresh';

		if( curAction != newAction ) {
			refreshbtn.setAttr( 'action', newAction );
			refreshbtn.setInnerRML( newAction );
		}
		return true;
	}

	void updateBrowserVisibility()
	{
		if( isGridHidden ) {
			servergrid.css( 'display', 'block' );
			navibar.css( 'display', 'block' );
			window.document.body.getElementById( 'serverbrowser-manual-container' ).css( 'display', 'none' );
		}
		isGridHidden = false;
	}

	bool onJoinThink()
	{
		if( isUpdating != serverBrowser.isUpdating() ) {
			isUpdating = serverBrowser.isUpdating();
			updateBrowserVisibility();
		}

		// keep the button title updated
		return updateRefreshTitle();
	}

	void onServerBrowserRowAdd( Element @self, Event @ev )
	{
		ElementDataGrid @grid = @self; // implicit cast to ElementDataGrid
		if( @grid == null ) {
			// not a datagrid
			return;
		}

		progresscounter.setInnerRML( '' + browserDataSource.numRows( 'normal' ) );
	}

	void formatServerInfoBlock( Element @el, const String &in table, int sel )
	{
		String hostnameRML = '';
		hostnameRML = '<field formatter="colorcode" value="' + browserDataSource.getField( table, sel, 'hostname' ) + '" />';

		String levelshotRML = '';
		levelshotRML = '<levelshot src="' + browserDataSource.getField( table, sel, 'map' ) + '" />';

		String infoRML = '';

		// mapname
		infoRML += StringUtils::Format( _T( 'Map: %s' ), browserDataSource.getField( table, sel, 'map' ) ) + '<br/>';

		// players
		infoRML += StringUtils::Format( _T( 'Players: %s' ), browserDataSource.getField( table, sel, 'players' ) ) + '<br/>';

		// gametype
		infoRML += StringUtils::Format( _T( 'Gametype: %s' ), browserDataSource.getField( table, sel, 'gametype' ) ) + '<br/>';

		// bots
		const String @bots = browserDataSource.getField( table, sel, 'bots' );
		if ( !bots.empty() && bots != '&nbsp;' && bots != '0' ) {
			infoRML += StringUtils::Format( _T( 'Bots: %s' ),  bots ) + '<br/>';
		}

		// mod directory
		const String @mod = browserDataSource.getField( table, sel, 'mod' );
		if ( !mod.empty() && mod != '&nbsp;' ) {
			infoRML += StringUtils::Format( _T( 'Mod: %s' ),  mod ) + '<br/>';
		}

		// ping
		infoRML += StringUtils::Format( _T( 'Ping: %s' ),  browserDataSource.getField( table, sel, 'ping' ) ) + '<br/>';

		// address
		infoRML += StringUtils::Format( _T( 'Address: %s' ), browserDataSource.getField( table, sel, 'address' ) ) + '<br/>';

		infoRML = '<div>' + infoRML + '</div>';

		el.css( 'display', 'block' ).setInnerRML( hostnameRML + '<br/><br/>' + levelshotRML + '<br/>' + infoRML );
	}

	void onServerBrowserRowSelect( Element @elem, Event @ev )
	{
		if( @serverblock == null ) {
			return;
		}
		if( @browserDataSource == null ) {
			return;
		}

		// get selected row and column indices
		int selectedRow = ev.getParameter( 'index', -1 );
		int selectedCol = ev.getParameter( 'column_index', -1 );

		if( selectedRow < 0 ) {
			// header click
			if( selectedCol > 0 ) {
				serverBrowser.sortByField( cast<ElementDataGrid>(servergrid).getFields( selectedCol )[0] );
			}
			return;
		}

		connectbtn.css( 'display', 'inline-block' );
		favoritebtn.css( 'display', 'inline-block' );

		bool isFavorite = browserDataSource.getField( 'normal', selectedRow, 'favorite' ) == 'yes';
		if( isFavorite )
			favoritebtn.setInnerRML( 'Remove from favorites' );
		else
			favoritebtn.setInnerRML( 'Add to favorites' );

		formatServerInfoBlock( @serverblock, 'normal', selectedRow );
	}

	void onServerBrowserRowChange( Element @self, Event @ev )
	{
		ElementDataGrid @grid = @self; // implicit cast to ElementDataGrid
		if( @grid == null ) {
			// not a datagrid
			return;
		}

		int numRowsChanged = ev.getParameter( 'num_rows_changed', 0 );
		if( numRowsChanged == 0 ) {
			return;
		}

		int firstRowChanged = ev.getParameter( 'first_row_changed', 0 );

		String prop = servergrid.getProp( 'selected-row' );
		int selectedRowIndex = prop.empty() ? -1 : prop.toInt();

		for( int i = 0; i < numRowsChanged; i++ ) {
			int rowIndex = firstRowChanged + i;
			Element @row = grid.getRow( rowIndex );

			// we only track whether the server has been (un)bookmarked
			bool isFavorite = browserDataSource.getField( 'normal', rowIndex, 'favorite' ) == 'yes';

			if( rowIndex == selectedRowIndex ) {
				// update the button
				if( isFavorite )
					favoritebtn.setInnerRML( 'Remove from favorites' );
				else
					favoritebtn.setInnerRML( 'Add to favorites' );
			}
		}
	}

	void onServerBrowserRowRemove( Element @self, Event @ev )
	{
		if( @servergrid == null || @ev == null ) {
			return;
		}

		int numRowsRemoved = ev.getParameter( 'num_rows_removed', 0 );
		if( numRowsRemoved == 0 ) {
			return;
		}

		int firstRowRemoved = ev.getParameter( 'first_row_removed', 0 );

		String prop = servergrid.getProp( 'selected-row' );
		int selectedRowIndex = prop.empty() ? -1 : prop.toInt();

		if( selectedRowIndex >= firstRowRemoved && selectedRowIndex < firstRowRemoved + numRowsRemoved ) {
			// clear/hide the infoblock
			serverblock.css( 'display', 'none' );
			connectbtn.css( 'display', 'none' );
			favoritebtn.css( 'display', 'none' );
		}
	}

	void onServerBrowserRowActivate( Element @elem, Event @ev )
	{
		connectToSelectedServer();
	}

	void onConnectButtonClick( Element @elem, Event @ev )
	{
		connectToSelectedServer();
	}

	void connectToSelectedServer( void )
	{
		if( @servergrid == null ) {
			return;
		}
		if( @browserDataSource == null ) {
			return;
		}

		String prop = servergrid.getProp( 'selected-row' );
		if( prop != '' )
		{
			int selectedRow = prop.toInt();
			if( selectedRow >= 0 )
			{
				String address = browserDataSource.getField( 'normal', selectedRow, 'address' );
				if( address.empty() ) {
					return;
				}

				// connect to server
				game.exec( 'connect "' + address + '"\n' );
			}
		}
	}

	bool toggleFavoriteOnSelectedServer( void )
	{
		String address = '';
		bool isFavorite = false;

		if( @servergrid == null ) {
			return false;
		}
		if( @browserDataSource == null ) {
			return false;
		}

		String prop = servergrid.getProp( 'selected-row' );
		if( prop != '' ) {
			int selectedRow = prop.toInt();
			if( selectedRow >= 0 ) {
				address = browserDataSource.getField( 'normal', selectedRow, 'address' );
				isFavorite = browserDataSource.getField( 'normal', selectedRow, 'favorite' ) == 'yes';
			}
		}

		if( address.empty() )
			return false;

		bool add = !isFavorite;
		if( add )
			Favorites::add( address );
		else
			Favorites::remove( address );

		return add;
	}

	void onFavoriteButtonClick( Element @elem, Event @ev )
	{
		toggleFavoriteOnSelectedServer();
	}

	void precacheStuff( Element @body, Event @event )
	{
		window.preload( 'options.rml' );
		window.preload( 'options_player.rml' );
		window.preload( 'options_video.rml' );
		window.preload( 'options_input.rml' );
		window.preload( 'options_audio.rml' );
	}

	</script>
</head>
<body template="baseui" onload="$onJoinLoad" onshow="$onJoinShow" onhide="$onJoinHide" onregisterworldmodel="$precacheStuff">
	<div id="sidebar">
		<div id="sidebar2">
			<a href="#" onclick="animOpenMenu('game_join.rml');">Match browser</a>
			<a href="#" onclick="animOpenMenu('game_local.rml');">Local game</a>
			<a href="#" onclick="animOpenMenu('game_demos.rml');">Demo browser</a>

			<button id="refresh-btn" onClick="$onRefreshButtonClick">Refresh</button>
			<button id="connect-btn" onClick="$onConnectButtonClick">Connect</button>
			<button id="favorite-btn" onClick="$onFavoriteButtonClick">Add to favorites</button>

			<div id="serverblock" class="infoblock" />
		</div>
	</div>
	<div id="leftside">
		<div id="serverbrowser-container" class="dropshadow">
			<div id="serverbrowser_frame">
				<datagrid id="serverbrowser_datagrid"
					onrowadd="$onServerBrowserRowAdd"
					onrowselect="$onServerBrowserRowSelect"
					onrowchange="$onServerBrowserRowChange"
					onrowremove="$onServerBrowserRowRemove"
					onrowactivate="$onServerBrowserRowActivate">
					<col fields="cleanname" width="80%">Hostname</col>
					<col fields="players" width="10%">Players</col>
					<col fields="ping" width="10%">Ping</col>
				</datagrid>
			</div>
		</div>
	</div>
</body>
</rml>
