package com.mehmetakiftutuncu.eshotroid.activity;
import java.util.ArrayList;
import android.annotation.TargetApi;
import android.content.Intent;
import android.content.res.Configuration;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.app.ActionBarDrawerToggle;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.GravityCompat;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarActivity;
import android.support.v7.widget.SearchView;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import com.mehmetakiftutuncu.eshotroid.BuildConfig;
import com.mehmetakiftutuncu.eshotroid.R;
import com.mehmetakiftutuncu.eshotroid.adapter.BusListAdapter;
import com.mehmetakiftutuncu.eshotroid.adapter.DrawerMenuListAdapter;
import com.mehmetakiftutuncu.eshotroid.adapter.MainPagesFragmentPagerAdapter;
import com.mehmetakiftutuncu.eshotroid.database.BusDatabase;
import com.mehmetakiftutuncu.eshotroid.fragment.AllBussesFragment;
import com.mehmetakiftutuncu.eshotroid.fragment.FavoriteBussesFragment;
import com.mehmetakiftutuncu.eshotroid.model.Bus;
import com.mehmetakiftutuncu.eshotroid.task.GetListOfBussesPageTask;
import com.mehmetakiftutuncu.eshotroid.utility.Constants;
/** Main activity of the application which contains a {@link ViewPager} for
* switching between three main pages of the application; favorite busses, all
* busses and Kent Kart balance
*
* @author mehmetakiftutuncu */
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class Main extends ActionBarActivity
implements SearchView.OnQueryTextListener,
MenuItemCompat.OnActionExpandListener,
AllBussesFragment.AllBussesListener,
FavoriteBussesFragment.FavoriteBussesListener
{
/** A {@link FragmentPagerAdapter} for switching between pages */
private MainPagesFragmentPagerAdapter pagerAdapter;
/** A {@link ViewPager} containing the pages to switch */
private ViewPager viewPager;
/** {@link DrawerLayout} for the activity to show a drawer menu */
private DrawerLayout drawerMenu;
/** {@link ListView} for the drawer menu containing menu items */
private ListView drawerMenuList;
/** {@link ActionBarDrawerToggle} of the {@link Main#drawerMenu} to handle
* opening and closing of drawer menu */
private ActionBarDrawerToggle drawerMenuToggle;
/** {@link SearchView} to perform searches */
private SearchView searchView;
/** Reference to the refresh item in the action bar menu */
private MenuItem refreshMenuItem;
/** First visible position in the all busses list, this will be used to
* restore the list to the position it was left */
private int firstVisiblePosition = -1;
/** Tag for debugging */
private static final String LOG_TAG = "Eshotroid_Main";
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
if(!PreferenceManager.getDefaultSharedPreferences(this).getBoolean(Constants.IS_SETUP_WIZARD_FINISHED, false))
{
// Run setup wizard
startActivity(new Intent(this, Welcome.class));
finish();
return;
}
setContentView(R.layout.activity_main);
if(BuildConfig.DEBUG) Log.d(LOG_TAG, "Creating main activity...");
// Create and initialize drawer menu
initializeDrawerMenu();
/* Show home button in the action bar which will in fact trigger drawer
* menu */
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
// Create and initialize pages
initializePages();
}
@Override
public void onListOfBussesLoaded()
{
if(BuildConfig.DEBUG) Log.d(LOG_TAG, "Loading list of all busses...");
// Read busses from the database
BusDatabase db = BusDatabase.getDatabase(this);
ArrayList<Bus> listOfBusses = db.get();
db.closeDatabase();
// If no busses exist on the database
if(listOfBusses.size() == 0)
{
if(BuildConfig.DEBUG) Log.d(LOG_TAG, "List of all busses doesn't exist in database. Downloading...");
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
new GetListOfBussesPageTask(this, pagerAdapter.getAllBussesFragment()).executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
else
new GetListOfBussesPageTask(this, pagerAdapter.getAllBussesFragment()).execute();
}
else
{
if(BuildConfig.DEBUG) Log.d(LOG_TAG, "List of all busses is loaded from database.");
// Set the adapter
pagerAdapter.getAllBussesFragment().setBusListAdapter(new BusListAdapter(this, listOfBusses));
// Set the scroll position if it was changed before
if(firstVisiblePosition != -1)
{
pagerAdapter.getAllBussesFragment().getListView().setSelectionFromTop(firstVisiblePosition, 0);
firstVisiblePosition = -1;
}
}
}
@Override
public void onSetBusSelected(ListView listView)
{
// Set the item click listener
listView.setOnItemClickListener(new OnItemClickListener()
{
@Override
public void onItemClick(AdapterView<?> adapter, View view, int position, long id)
{
// Get bus list adapter
BusListAdapter busListAdapter = pagerAdapter
.getAllBussesFragment().getBusListAdapter();
// Get selected bus
Bus bus = busListAdapter.getItem(position);
if(BuildConfig.DEBUG) Log.d(LOG_TAG, "Starting times activity for " + bus.getNumber() + "...");
// Save current list position
firstVisiblePosition = pagerAdapter.getAllBussesFragment().getListView().getFirstVisiblePosition();
// Start times activity with selected bus number
Intent intent = new Intent(Main.this, Times.class);
intent.putExtra(Constants.BUS_NUMBER_EXTRA, bus.getNumber());
startActivity(intent);
}
});
}
@Override
public void onFavoriteBussesLoaded()
{
if(BuildConfig.DEBUG) Log.d(LOG_TAG, "Loading favorite busses...");
// Read busses from the database
BusDatabase db = BusDatabase.getDatabase(this);
ArrayList<Bus> listOfBusses = db.get();
db.closeDatabase();
// If some busses exist on the database
if(listOfBusses.size() != 0)
{
// Create favorited busses list
ArrayList<Bus> favoritedBusses = new ArrayList<Bus>();
// Add favorited busses to the list
for(Bus i : listOfBusses)
{
if(i.isFavorited())
{
favoritedBusses.add(i);
}
}
// Set the adapter
pagerAdapter.getFavoriteBussesFragment().setBusListAdapter(new BusListAdapter(this, favoritedBusses));
}
}
@Override
public void onSetFavoritedBusSelected(ListView listView)
{
// Set the item click listener
listView.setOnItemClickListener(new OnItemClickListener()
{
@Override
public void onItemClick(AdapterView<?> adapter, View view, int position, long id)
{
// Get favorite bus list adapter
BusListAdapter busListAdapter = pagerAdapter
.getFavoriteBussesFragment().getBusListAdapter();
// Get selected bus
Bus bus = busListAdapter.getItem(position);
if(BuildConfig.DEBUG) Log.d(LOG_TAG, "Starting times activity for " + bus.getNumber() + "...");
// Start times activity with selected bus number
Intent intent = new Intent(Main.this, Times.class);
intent.putExtra(Constants.BUS_NUMBER_EXTRA, bus.getNumber());
startActivity(intent);
}
});
}
/** This method is called when menu (ActionBar items) is being created */
@Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Check if the drawer menu is open
boolean isDrawerOpen = drawerMenu.isDrawerOpen(drawerMenuList);
// If drawer is not open
if(!isDrawerOpen)
{
// Get current page id
int currentPage = viewPager.getCurrentItem();
// Check current page id to decide which items to show
switch(currentPage)
{
// Favorite busses, no items needed
case Constants.PAGE_ID_FAVORITE_BUSSES:
break;
// All busses, search and refresh needed
case Constants.PAGE_ID_ALL_BUSSES:
// Inflate the search menu and add it
getMenuInflater().inflate(R.menu.search, menu);
// Get the search menu item and search view
MenuItem searchItem = menu.findItem(R.id.item_search);
searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
// Set the query hint
searchView.setQueryHint(getString(R.string.menu_search_hint));
// Set search listeners
MenuItemCompat.setOnActionExpandListener(searchItem, this);
searchView.setOnQueryTextListener(this);
// Inflate the refresh menu and add it
getMenuInflater().inflate(R.menu.refresh, menu);
// Get refresh menu item
refreshMenuItem = menu.findItem(R.id.item_refresh);
// Show progress if necessary
if(pagerAdapter.getAllBussesFragment().isRefreshing())
{
if(BuildConfig.DEBUG) Log.d(LOG_TAG, "Setting refresh button as progress for all busses page...");
MenuItemCompat.setActionView(refreshMenuItem, R.layout.item_progress);
}
break;
// Favorite busses, no items needed
case Constants.PAGE_ID_KENT_KART_BALANCE:
// Inflate the refresh menu and add it
getMenuInflater().inflate(R.menu.refresh, menu);
// Get refresh menu item and hide it
refreshMenuItem = menu.findItem(R.id.item_refresh);
refreshMenuItem.setVisible(false);
// Show progress if necessary
if(pagerAdapter.getKentKartBalanceFragment().isQuerying())
{
refreshMenuItem.setVisible(true);
if(BuildConfig.DEBUG) Log.d(LOG_TAG, "Setting refresh button as progress for all Kent Kart page...");
MenuItemCompat.setActionView(refreshMenuItem, R.layout.item_progress);
}
break;
}
}
return super.onCreateOptionsMenu(menu);
}
/** This method is called when a menu item is clicked */
@Override
public boolean onOptionsItemSelected(MenuItem item)
{
/* Pass the event to ActionBarDrawerToggle, if it returns true, then it
* has handled the app icon touch event */
if(drawerMenuToggle.onOptionsItemSelected(item))
{
if(BuildConfig.DEBUG) Log.d(LOG_TAG, "Home button is selected for drawer.");
// Action is completed because drawer is opened
return true;
}
// Check which menu item is selected
switch(item.getItemId())
{
// Search
case R.id.item_search:
// Expand search view
MenuItemCompat.expandActionView(item);
break;
case R.id.item_refresh:
// Get current page id
int currentPage = viewPager.getCurrentItem();
// Check current page id to decide what to refresh
switch(currentPage)
{
// Refresh the list of all busses
case Constants.PAGE_ID_ALL_BUSSES:
if(BuildConfig.DEBUG) Log.d(LOG_TAG, "Refreshing the list of all busses...");
// Start downloading
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
new GetListOfBussesPageTask(this,
pagerAdapter.getAllBussesFragment()).executeOnExecutor(AsyncTask.SERIAL_EXECUTOR);
else
new GetListOfBussesPageTask(this,
pagerAdapter.getAllBussesFragment()).execute();
break;
}
break;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onPostCreate(Bundle savedInstanceState)
{
super.onPostCreate(savedInstanceState);
// Sync the toggle state after onRestoreInstanceState has occurred.
drawerMenuToggle.syncState();
}
@Override
public void onConfigurationChanged(Configuration newConfig)
{
super.onConfigurationChanged(newConfig);
// Apply the configuration changes to drawer menu as well
drawerMenuToggle.onConfigurationChanged(newConfig);
}
/** This method is called when the query text in {@link Main#searchView} is
* changed */
@Override
public boolean onQueryTextChange(String query)
{
if(BuildConfig.DEBUG) Log.d(LOG_TAG, "Searching for " + query + "...");
searchBusses(query);
return true;
}
/** This method is called when the query text in {@link Main#searchView} is
* submitted */
@Override
public boolean onQueryTextSubmit(String query)
{
if(BuildConfig.DEBUG) Log.d(LOG_TAG, "Search query submitted " + query + ".");
searchView.clearFocus();
return false;
}
/** This method is called when the {@link Main#searchView} is collapsed */
@Override
public boolean onMenuItemActionCollapse(MenuItem item)
{
if(BuildConfig.DEBUG) Log.d(LOG_TAG, "Search is closed.");
searchBusses(null);
return true;
}
/** This method is called when the {@link Main#searchView} is expanded */
@Override
public boolean onMenuItemActionExpand(MenuItem item)
{
if(BuildConfig.DEBUG) Log.d(LOG_TAG, "Search is opened.");
return true;
}
/** Toggles the UI mode to either ready or waiting (hides other content and
* shows a progress bar)
*
* @param isWaiting If true, mode will change to waiting, else it will
* change to ready mode
* @param pageId Id of the page whose contents are being refreshed */
public void toggleMode(boolean isRefreshing, int pageId)
{
if(refreshMenuItem != null)
{
/* Check the current page to decide for what page refreshing state
* should change */
//switch(viewPager.getCurrentItem())
switch(pageId)
{
case Constants.PAGE_ID_ALL_BUSSES:
if(BuildConfig.DEBUG) Log.d(LOG_TAG, "Setting refreshing state for all busses page as " + isRefreshing + "...");
pagerAdapter.getAllBussesFragment().setRefreshing(isRefreshing);
break;
case Constants.PAGE_ID_KENT_KART_BALANCE:
if(BuildConfig.DEBUG) Log.d(LOG_TAG, "Setting refreshing state for Kent Kart page as " + isRefreshing + "...");
pagerAdapter.getKentKartBalanceFragment().setQuerying(isRefreshing);
break;
}
// Cause action bar menu to be created again
supportInvalidateOptionsMenu();
}
}
/** @return {@link Main#viewPager} */
public ViewPager getViewPager()
{
return viewPager;
}
/** Creates and initializes pages */
private void initializePages()
{
if(BuildConfig.DEBUG) Log.d(LOG_TAG, "Initializing pages...");
// Get view pager
viewPager = (ViewPager) findViewById(R.id.viewPager_main);
/* Set off screen page limit to 2 indicating that there may be 2
* non-visible pages in memory */
viewPager.setOffscreenPageLimit(2);
if(BuildConfig.DEBUG) Log.d(LOG_TAG, "Setting main pages fragment pager adapter...");
/* Create the adapter that will return a fragment for each of the three
* main pages of the application */
pagerAdapter = new MainPagesFragmentPagerAdapter(this, getSupportFragmentManager());
// Set up the ViewPager with the pages adapter.
viewPager.setAdapter(pagerAdapter);
// Set page change listener to update options menu for each page
viewPager.setOnPageChangeListener(new OnPageChangeListener()
{
@Override
public void onPageSelected(int arg0)
{
// Cause action bar menu to be created again
supportInvalidateOptionsMenu();
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2)
{
}
@Override
public void onPageScrollStateChanged(int arg0)
{
}
});
// Going to select the default page on startup
if(BuildConfig.DEBUG) Log.d(LOG_TAG, "Selecting default page...");
// Read busses from the database
BusDatabase db = BusDatabase.getDatabase(this);
ArrayList<Bus> listOfBusses = db.get();
db.closeDatabase();
// Assume there is no favorited bus
boolean hasFavorited = false;
// Add favorited busses to the list
for(Bus i : listOfBusses)
{
if(i.isFavorited())
{
hasFavorited = true;
break;
}
}
// If found any favorited bus
if(hasFavorited)
{
if(BuildConfig.DEBUG) Log.d(LOG_TAG, "Selecting favorite busses page as default...");
// Start with favorited busses page
viewPager.setCurrentItem(Constants.PAGE_ID_FAVORITE_BUSSES);
}
else
{
if(BuildConfig.DEBUG) Log.d(LOG_TAG, "Selecting all busses page as default...");
// By default start with all busses page
viewPager.setCurrentItem(Constants.PAGE_ID_ALL_BUSSES);
}
}
/** Creates and initializes drawer menu */
private void initializeDrawerMenu()
{
if(BuildConfig.DEBUG) Log.d(LOG_TAG, "Initializing drawer menu...");
// Get drawer menu and drawer menu list
drawerMenu = (DrawerLayout) findViewById(R.id.drawerLayout_main);
drawerMenuList = (ListView) findViewById(R.id.listView_drawerMenu);
// Set this to let back button open the drawable menu, and when it is opened, finish the activtiy
drawerMenu.setFocusableInTouchMode(false);
// Set menu items
String[] drawerMenuItems = new String[]
{
getString(R.string.drawerMenu_rate),
getString(R.string.drawerMenu_contact),
getString(R.string.drawerMenu_website),
getString(R.string.drawerMenu_help),
getString(R.string.drawerMenu_about)
};
if(BuildConfig.DEBUG) Log.d(LOG_TAG, "Setting drawer menu adapter...");
// Set the drawer adapter
drawerMenuList.setAdapter(new DrawerMenuListAdapter(this, drawerMenuItems));
// Set the drawer menu list item click listener
drawerMenuList.setOnItemClickListener(new AdapterView.OnItemClickListener()
{
@Override
public void onItemClick(AdapterView<?> adapter, View view, int position, long id)
{
String selectedItem = (String) adapter.getItemAtPosition(position);
if(selectedItem.equals(getString(R.string.drawerMenu_rate)))
{
Intent intentRate = new Intent(Intent.ACTION_VIEW, Uri.parse(Constants.APPLICATION_URL));
startActivity(Intent.createChooser(intentRate, getString(R.string.drawerMenu_rate)));
}
else if(selectedItem.equals(getString(R.string.drawerMenu_contact)))
{
Intent intentContact = new Intent(Intent.ACTION_SEND);
intentContact.setType("message/rfc822");
intentContact.putExtra(Intent.EXTRA_EMAIL, new String[] {Constants.CONTACT});
intentContact.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.about_title));
startActivity(Intent.createChooser(intentContact, getString(R.string.drawerMenu_contact)));
}
else if(selectedItem.equals(getString(R.string.drawerMenu_website)))
{
Intent intentWebsite = new Intent(Intent.ACTION_VIEW, Uri.parse(Constants.WEBSITE_URL));
startActivity(Intent.createChooser(intentWebsite, getString(R.string.drawerMenu_website)));
}
else if(selectedItem.equals(getString(R.string.drawerMenu_help)))
{
startActivity(new Intent(Main.this, Help.class));
}
else if(selectedItem.equals(getString(R.string.drawerMenu_about)))
{
startActivity(new Intent(Main.this, About.class));
}
}
});
if(BuildConfig.DEBUG) Log.d(LOG_TAG, "Setting drawer menu toggle...");
// Set drawer toggle
drawerMenuToggle = new ActionBarDrawerToggle(this, drawerMenu,R.drawable.ic_drawer,
R.string.drawerMenu_title, R.string.app_name)
{
@Override
public void onDrawerOpened(View drawerView)
{
if(BuildConfig.DEBUG) Log.d(LOG_TAG, "Drawer menu is opened.");
// Change title
getSupportActionBar().setTitle(R.string.drawerMenu_title);
// Cause action bar menu to be created again
supportInvalidateOptionsMenu();
}
@Override
public void onDrawerClosed(View drawerView)
{
if(BuildConfig.DEBUG) Log.d(LOG_TAG, "Drawer menu is closed.");
// Change title
getSupportActionBar().setTitle(R.string.app_name);
// Cause action bar menu to be created again
supportInvalidateOptionsMenu();
}
};
drawerMenu.setDrawerListener(drawerMenuToggle);
// Set the drawer menu shadow
drawerMenu.setDrawerShadow(R.drawable.drawer_shadow, GravityCompat.START);
}
/** Searches busses with the given query */
private void searchBusses(String query)
{
// Get bus list adapter
BusListAdapter busListAdapter = pagerAdapter.getAllBussesFragment().getBusListAdapter();
// If adapter is set and can be searched
if(busListAdapter != null && busListAdapter.getFilter() != null)
{
// Filter the list according to the search query
busListAdapter.getFilter().filter(query);
busListAdapter.notifyDataSetChanged();
}
}
}