package com.charlesmadere.android.classygames;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.util.Log;
import android.widget.Toast;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem;
import com.charlesmadere.android.classygames.models.Game;
import com.charlesmadere.android.classygames.models.Notification;
import com.charlesmadere.android.classygames.models.Person;
import com.charlesmadere.android.classygames.settings.PreferenceActivity;
import com.charlesmadere.android.classygames.utilities.Utilities;
public final class GameFragmentActivity extends BaseFragmentActivity implements
GamesListFragment.Listeners,
GenericGameFragment.Listeners,
MyStatsDialogFragment.Listeners
{
private final static String LOG_TAG = Utilities.LOG_TAG + " - GameFragmentActivity";
private final static String KEY_ACTION_BAR_TITLE = "KEY_ACTION_BAR_TITLE";
public final static String KEY_NOTIFICATION = "KEY_NOTIFICATION";
private EmptyGameFragment emptyGameFragment;
private GamesListFragment gamesListFragment;
private GenericGameFragment genericGameFragment;
private MyStatsDialogFragment myStatsDialogFragment;
@Override
protected void onCreate(final Bundle savedInstanceState)
// I'm sorry that this method is so crazy. I really am. But there's a bunch
// of different things that it does, so it's necessary. Check the comments
// throughout the method to follow along.
{
super.onCreate(savedInstanceState, R.string.games_list, false);
setContentView(R.layout.game_fragment_activity);
setResult(RESULT_FIRST_USER);
final FragmentManager fManager = getSupportFragmentManager();
if (savedInstanceState == null)
// Checks to see if the savedInstanceState object is null. If this
// object is null then we're not rebuilding this FragmentActivity due
// to an orientation change. This means that this FragmentActivity is
// completely fresh and brand new.
{
final FragmentTransaction fTransaction = fManager.beginTransaction();
if (isDeviceLarge())
// Checks to see if this is a large device. If this is a large
// device then we will load in the multi pane layout.
{
emptyGameFragment = new EmptyGameFragment();
fTransaction.add(R.id.game_fragment_activity_fragment_game, emptyGameFragment);
gamesListFragment = (GamesListFragment) fManager.findFragmentById(R.id.game_fragment_activity_fragment_games_list_fragment);
}
else
// This is a small device. We will load in the single pane layout.
{
gamesListFragment = new GamesListFragment();
fTransaction.add(R.id.game_fragment_activity_container, gamesListFragment);
}
fTransaction.commit();
}
else
// The savedInstanceState object is not null. This means that the
// Android device probably just went through an orientation change.
// We're going to recover this FragmentActivity from the data stored
// in the savedInstanceState object.
{
// Read in the previously stored title for the Action Bar. If the
// title was not found, then the R.string.games_list String will be
// loaded in and used instead.
CharSequence actionBarTitle = savedInstanceState.getCharSequence(KEY_ACTION_BAR_TITLE);
if (actionBarTitle == null || !Utilities.validString(actionBarTitle.toString()))
{
actionBarTitle = getString(R.string.games_list);
}
if (isDeviceLarge())
// Checks to see if this is a large device. If this is a large
// device then we will load in the multi pane layout.
{
gamesListFragment = (GamesListFragment) fManager.findFragmentById(R.id.game_fragment_activity_fragment_games_list_fragment);
final Fragment fragment = fManager.findFragmentById(R.id.game_fragment_activity_fragment_game);
if (fragment instanceof EmptyGameFragment)
{
emptyGameFragment = (EmptyGameFragment) fragment;
}
else
{
genericGameFragment = (GenericGameFragment) fragment;
updateActionBar(actionBarTitle, true);
}
}
else
// This is a small device. We will load in the single pane layout.
{
final Fragment fragment = fManager.findFragmentById(R.id.game_fragment_activity_container);
if (fragment instanceof GamesListFragment)
{
gamesListFragment = (GamesListFragment) fragment;
}
else
{
genericGameFragment = (GenericGameFragment) fragment;
updateActionBar(actionBarTitle, true);
}
}
}
// Checks to see if the reason that this class is running is because
// the user tapped a Classy Games notification in their notifications
// bar.
checkIfNotificationWasTapped();
}
@Override
protected void onActivityResult(final int requestCode, final int resultCode, final Intent data)
// This method will be run when the NewGameFragmentActivity returns some
// data back. That data pertains to who the current Android user wants to
// create a game against.
{
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK)
// Check the result code as returned from NewGameFragmentActivity. If a
// friend was selected, then this means that the current Android user
// wants to start a new game against that selected user.
{
// Retrieve the data as returned from NewGameFragmentActivity. It
// could be malformed, we'll check for that below.
final Bundle extras = data.getExtras();
if (extras != null && !extras.isEmpty())
// Ensure that the returned data is not totally garbled.
{
final Person friend = (Person) extras.getSerializable(NewGameFragmentActivity.KEY_FRIEND);
final byte whichGame = extras.getByte(NewGameFragmentActivity.KEY_WHICH_GAME);
if (friend.isValid() && Game.isWhichGameValid(whichGame))
// Ensure that we received proper data from
// NewGameFragmentActivity.
{
final Game game = new Game(friend, whichGame);
onGameSelected(game);
}
else
{
Log.e(LOG_TAG, "onActivityResult() received game data that was malformed.");
}
}
}
}
@Override
public void onBackPressed()
{
if (myStatsDialogFragment != null && myStatsDialogFragment.onBackPressed())
{
}
else if (genericGameFragment != null && genericGameFragment.onBackPressed())
{
}
else if (gamesListFragment != null && gamesListFragment.onBackPressed())
{
}
else
{
super.onBackPressed();
if (genericGameFragment == null || !genericGameFragment.isVisible())
{
updateActionBar(R.string.games_list, false);
}
}
}
@Override
public boolean onCreateOptionsMenu(final Menu menu)
{
final MenuInflater inflater = getSupportMenuInflater();
inflater.inflate(R.menu.game_fragment_activity, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(final MenuItem item)
{
switch (item.getItemId())
{
case android.R.id.home:
onBackPressed();
break;
// case R.id.game_fragment_activity_menu_my_stats:
// final FragmentManager fManager = getSupportFragmentManager();
// final FragmentTransaction fTransaction = fManager.beginTransaction();
// fTransaction.addToBackStack(null);
// myStatsDialogFragment = new MyStatsDialogFragment();
// myStatsDialogFragment.show(fTransaction, null);
// break;
case R.id.game_fragment_activity_menu_new_game:
if (isDeviceLarge() && genericGameFragment != null && genericGameFragment.isVisible())
{
onBackPressed();
}
final Intent newGameIntent = new Intent(this, NewGameFragmentActivity.class);
startActivityForResult(newGameIntent, RESULT_FIRST_USER);
break;
case R.id.game_fragment_activity_menu_settings:
final Intent settingsIntent = new Intent(this, PreferenceActivity.class);
startActivity(settingsIntent);
break;
default:
return super.onOptionsItemSelected(item);
}
return true;
}
@Override
protected void onSaveInstanceState(final Bundle outState)
{
final CharSequence actionBarTitle = getActionBarTitle();
outState.putCharSequence(KEY_ACTION_BAR_TITLE, actionBarTitle);
super.onSaveInstanceState(outState);
}
/**
* Checks to see if the reason that the user is currently at this class
* (GameFragmentActivity) is because they tapped a notification in their
* notifications bar. If that turns out to be the reason, then this method
* will load in the game that the notification pertains to.
*/
private void checkIfNotificationWasTapped()
{
// Retrieve an Intent that was given to this class. It's possible that
// no Intent was given to this class (in this case the resulting value
// should be null). We need to do this because when someone taps a
// Classy Games notification in their notifications bar, that action
// triggers an Intent to be sent into this method. That Intent will
// then include a bunch of information about the tapped notification.
final Intent intent = getIntent();
if (intent != null)
{
final Bundle arguments = intent.getExtras();
if (arguments != null && !arguments.isEmpty())
// Check to see if the Intent contains any arguments.
{
final Notification notification = (Notification) arguments.getSerializable(KEY_NOTIFICATION);
if (notification != null)
// Check the data gathered from the Intent. If a single piece
// of this data is found to be invalid, then we will not act
// upon the tapped notification.
{
final Game game = new Game(notification.getPerson(), notification.getWhichGame(), notification.getGameId());
onGameSelected(game);
}
}
}
}
/**
* Ensures that the gamesListFragment Fragment object is not null.
*/
private void getGamesListFragment()
{
if (gamesListFragment == null)
{
final FragmentManager fManager = getSupportFragmentManager();
if (isDeviceLarge())
{
gamesListFragment = (GamesListFragment) fManager.findFragmentById(R.id.game_fragment_activity_fragment_games_list_fragment);
}
else
{
final Fragment fragment = fManager.findFragmentById(R.id.game_fragment_activity_container);
if (fragment instanceof GamesListFragment)
{
gamesListFragment = (GamesListFragment) fragment;
}
else
{
Log.w(LOG_TAG, "getGamesListFragment() tried to grab the GamesListFragment but encountered weirdness!");
}
}
}
}
/**
* Checks to see what size screen this device has. This method will return
* true if the device has a large screen, and as such said device should be
* using the dual pane, fragment based, layout stuff.
*
* @return
* Returns true if this device has a large screen.
*/
private boolean isDeviceLarge()
{
return findViewById(R.id.game_fragment_activity_container) == null;
}
@Override
public void onGameSelected(final Game game)
{
if (isDeviceLarge() || (genericGameFragment == null || !genericGameFragment.isVisible()))
// This statement will validate as true if this Android device is large
// OR if EITHER of the following two statements are two: the
// genericGameFragment variable is null, OR the genericGameFragment
// variable is not visible.
{
if (genericGameFragment != null && genericGameFragment.isVisible())
// If the genericGameFragment variable is both not null and is
// visible. This means that a game is currently open and showing.
// We want to remove that game before proceeding with the showing
// of the newly selected game.
{
// Trigger a press of the back button. This will remove the
// game that is currently showing.
onBackPressed();
}
if (game.isGameCheckers())
{
genericGameFragment = CheckersGameFragment.newInstance(game.getId(), game.getWhichGame(), game.getPerson());
}
else if (game.isGameChess())
{
genericGameFragment = ChessGameFragment.newInstance(game.getId(), game.getWhichGame(), game.getPerson());
}
final FragmentTransaction fTransaction = getSupportFragmentManager().beginTransaction();
fTransaction.addToBackStack(null);
if (isDeviceLarge())
{
fTransaction.replace(R.id.game_fragment_activity_fragment_game, genericGameFragment);
}
else
{
fTransaction.setCustomAnimations(R.anim.slide_in, R.anim.slide_out, R.anim.slide_in_popped, R.anim.slide_out_popped);
fTransaction.add(R.id.game_fragment_activity_container, genericGameFragment);
}
fTransaction.commit();
if (game.isGameCheckers())
{
updateActionBar(getString(R.string.checkers_with_x, game.getPerson().getName()), true);
}
else if (game.isGameChess())
{
updateActionBar(getString(R.string.chess_with_x, game.getPerson().getName()), true);
}
else
{
Log.e(LOG_TAG, "Player tried creating a game which was not one we recognize...");
}
}
}
@Override
public void onRefreshSelected()
{
if (isDeviceLarge() && genericGameFragment != null && genericGameFragment.isVisible())
{
onBackPressed();
}
getGamesListFragment();
gamesListFragment.refreshGamesList();
}
@Override
public boolean isDeviceSmall()
{
return !isDeviceLarge();
}
@Override
public void onGetGameCancelled()
{
onBackPressed();
}
@Override
public void onGetGameDataError()
{
Toast.makeText(this, R.string.couldnt_create_the_game_as_malformed_data_was_detected, Toast.LENGTH_LONG).show();
onBackPressed();
}
@Override
public void onGetStatsDataError(final Exception e)
{
Log.e(LOG_TAG, "Exception in onGetStatsDataError!", e);
Toast.makeText(this, R.string.a_server_error_occurred_when_trying_to_get_your_stats_data, Toast.LENGTH_LONG).show();
onBackPressed();
}
@Override
public void onServerApiTaskFinished()
{
final FragmentManager fManager = getSupportFragmentManager();
fManager.popBackStack();
final FragmentTransaction fTransaction = fManager.beginTransaction();
if (isDeviceLarge())
{
if (emptyGameFragment == null)
{
emptyGameFragment = new EmptyGameFragment();
}
fTransaction.replace(R.id.game_fragment_activity_fragment_game, emptyGameFragment);
}
else
{
fTransaction.remove(genericGameFragment);
}
fTransaction.commit();
fManager.executePendingTransactions();
updateActionBar(R.string.games_list, false);
onRefreshSelected();
}
}