package com.adamnickle.deck.Game;
import android.content.Context;
import com.adamnickle.deck.Interfaces.ConnectionFragment;
import com.adamnickle.deck.Interfaces.GameConnection;
import com.adamnickle.deck.Interfaces.GameConnectionListener;
import java.io.File;
import java.util.HashMap;
import java.util.Iterator;
public class ServerGameConnection extends GameConnection
{
private HashMap< String, CardHolder > mPlayers;
private HashMap< String, CardHolder > mLeftPlayers;
public ServerGameConnection( ConnectionFragment connectionFragment )
{
super( connectionFragment );
mPlayers = new HashMap< String, CardHolder >();
mLeftPlayers = new HashMap< String, CardHolder >();
}
private void handleCardChanges( GameMessage message )
{
final CardHolder cardHolder = mPlayers.get( message.getReceiverID() );
if( !message.Handled )
{
message.Handled = true;
switch( message.getMessageType() )
{
case MESSAGE_RECEIVE_CARD:
final CardHolder removedFromCardHolder = mPlayers.get( message.getRemovedFromID() );
if( removedFromCardHolder != null )
{
this.removeCard( message.getOriginalSenderID(), removedFromCardHolder.getID(), message.getCard() );
}
cardHolder.addCard( message.getCard() );
break;
case MESSAGE_RECEIVE_CARDS:
cardHolder.addCards( message.getCards() );
break;
case MESSAGE_REMOVE_CARD:
cardHolder.removeCard( message.getCard() );
break;
case MESSAGE_REMOVE_CARDS:
cardHolder.removeCards( message.getCards() );
break;
case MESSAGE_CLEAR_CARDS:
cardHolder.clearCards();
break;
}
}
}
private void handleNewCardHolder( String deviceID, String deviceName )
{
CardHolder newPlayer = mLeftPlayers.remove( deviceID );
if( newPlayer == null )
{
newPlayer = new CardHolder( deviceID, deviceName );
}
if( mPlayers.size() > 0 )
{
// Send the new player information about already connected players
final CardHolder[] players = mPlayers.values().toArray( new CardHolder[ mPlayers.size() ] );
final GameMessage message = new GameMessage( GameMessage.MessageType.MESSAGE_CARD_HOLDERS, MOCK_SERVER_ADDRESS, newPlayer.getID() );
message.putCardHolders( players );
this.sendMessageToDevice( message, MOCK_SERVER_ADDRESS, newPlayer.getID() );
final GameMessage newPlayerMessage = new GameMessage( GameMessage.MessageType.MESSAGE_NEW_PLAYER, deviceID, null );
newPlayerMessage.putName( deviceName );
// Send new player to all connected remote players
for( CardHolder player : mPlayers.values() )
{
if( !player.getID().equals( getLocalPlayerID() ) && mConnectionFragment.isPlayerID( player.getID() ) )
{
newPlayerMessage.setReceiverID( player.getID() );
this.sendMessageToDevice( newPlayerMessage, deviceID, player.getID() );
}
}
if( !newPlayer.getID().equals( getLocalPlayerID() ) )
{
// Send new player to local player
newPlayerMessage.setReceiverID( getLocalPlayerID() );
this.sendMessageToDevice( newPlayerMessage, deviceID, getLocalPlayerID() );
}
}
mPlayers.put( deviceID, newPlayer );
if( newPlayer.getCardCount() > 0 )
{
Card[] cards = newPlayer.getCards();
newPlayer.clearCards();
this.sendCards( MOCK_SERVER_ADDRESS, newPlayer.getID(), cards );
}
}
/*******************************************************************
* ConnectionListener Methods
*******************************************************************/
@Override
public synchronized void onMessageHandle( GameConnectionListener listener, String originalSenderID, String receiverID, GameMessage message )
{
switch( message.getMessageType() )
{
case MESSAGE_RECEIVE_CARD:
final String cardHolderID = message.getRemovedFromID();
if( cardHolderID != null && !mPlayers.get( cardHolderID ).hasCard( message.getCard() ) )
{
return;
}
break;
}
if( receiverID.equals( MOCK_SERVER_ADDRESS ) )
{
switch( message.getMessageType() )
{
case MESSAGE_SET_NAME:
handleNewCardHolder( originalSenderID, message.getPlayerName() );
break;
case MESSAGE_RECEIVE_CARD:
//TODO Server received card from player
break;
case MESSAGE_CARD_HOLDERS:
final CardHolder[] cardHolders = message.getCardHolders();
for( CardHolder cardHolder : mPlayers.values() )
{
this.sendCardHolders( MOCK_SERVER_ADDRESS, cardHolder.getID(), cardHolders );
}
break;
}
}
else if( receiverID.equals( getLocalPlayerID() ) )
{
super.onMessageHandle( listener, originalSenderID, receiverID, message );
}
else if( !mConnectionFragment.isPlayerID( receiverID ) )
{
super.onMessageHandle( listener, originalSenderID, receiverID, message );
for( CardHolder cardHolder : mPlayers.values() )
{
if( mConnectionFragment.isPlayerID( cardHolder.getID() ) )
{
this.sendMessageToDevice( message, originalSenderID, cardHolder.getID() );
}
}
}
else
{
mConnectionFragment.sendDataToDevice( receiverID, GameMessage.serializeMessage( message ) );
}
this.handleCardChanges( message );
}
@Override
public synchronized void onDeviceConnect( String deviceID, String deviceName )
{
if( mConnectionFragment.isPlayerID( deviceID ) && !deviceID.equals( getLocalPlayerID() ) )
{
final CardHolder localPlayer = mPlayers.get( getLocalPlayerID() );
this.sendCardHolderName( MOCK_SERVER_ADDRESS, deviceID, localPlayer.getName() );
}
}
@Override
public void onConnectionStarted()
{
super.onConnectionStarted();
for( GameConnectionListener listener : mListeners )
{
listener.onServerConnect( MOCK_SERVER_ADDRESS, MOCK_SERVER_NAME );
}
}
@Override
public synchronized void onConnectionLost( String deviceID )
{
mLeftPlayers.put( deviceID, mPlayers.remove( deviceID ) );
final GameMessage message = new GameMessage( GameMessage.MessageType.MESSAGE_PLAYER_LEFT, deviceID, null );
// Send player left to all connected remote players
for( CardHolder player : mPlayers.values() )
{
if( !player.getID().equals( getLocalPlayerID() ) )
{
message.setReceiverID( player.getID() );
mConnectionFragment.sendDataToDevice( player.getID(), GameMessage.serializeMessage( message ) );
}
}
// Send player left to local player
message.setReceiverID( getLocalPlayerID() );
final byte data[] = GameMessage.serializeMessage( message );
this.onMessageReceive( deviceID, data.length, data );
}
/*******************************************************************
* GameConnection Methods
*******************************************************************/
@Override
public void startGame()
{
if( !isGameStarted() )
{
mConnectionFragment.startConnection();
}
}
@Override
public boolean saveGame( Context context, String saveName )
{
return GameSaveIO.saveGame(
context,
saveName,
mPlayers.values().toArray( new CardHolder[ mPlayers.size() ] ),
mLeftPlayers.values().toArray( new CardHolder[ mLeftPlayers.size() ] )
);
}
@Override
public boolean openGameSave( Context context, File gameSave )
{
final HashMap< String, CardHolder > players = new HashMap< String, CardHolder >();
if( GameSaveIO.openGameSave( gameSave, players, players ) )
{
mLeftPlayers.clear();
Iterator<CardHolder> cardHolderIterator = players.values().iterator();
while( cardHolderIterator.hasNext() )
{
final CardHolder cardHolder = cardHolderIterator.next();
if( mPlayers.containsKey( cardHolder.getID() ) )
{
this.sendGameOpen( MOCK_SERVER_ADDRESS, cardHolder.getID(), cardHolder.getCards() );
cardHolderIterator.remove();
}
}
mLeftPlayers = players;
return true;
}
else
{
return false;
}
}
@Override
public void sendMessageToDevice( GameMessage message, String senderID, String receiverID )
{
if( receiverID.equals( getLocalPlayerID() ) || receiverID.equals( MOCK_SERVER_ADDRESS ) || !mConnectionFragment.isPlayerID( receiverID ) )
{
final GameConnectionListener listener = this.findAppropriateListener( message );
this.onMessageHandle( listener, senderID, receiverID, message );
}
else
{
final byte[] data = GameMessage.serializeMessage( message );
mConnectionFragment.sendDataToDevice( receiverID, data );
}
this.handleCardChanges( message );
}
}