package com.github.andlyticsproject;

import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.graphics.PorterDuff;
import android.support.design.widget.NavigationView;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.app.Dialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.widget.Toolbar;
import android.support.v4.widget.SwipeRefreshLayout;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import com.github.andlyticsproject.Preferences.StatsMode;
import com.github.andlyticsproject.Preferences.Timeframe;
import com.github.andlyticsproject.about.AboutActivity;
import com.github.andlyticsproject.adsense.AdSenseClient;
import com.github.andlyticsproject.console.v2.DevConsoleRegistry;
import com.github.andlyticsproject.console.v2.DevConsoleV2;
import com.github.andlyticsproject.db.AndlyticsDb;
import com.github.andlyticsproject.io.StatsCsvReaderWriter;
import com.github.andlyticsproject.model.AdmobStats;
import com.github.andlyticsproject.model.AppInfo;
import com.github.andlyticsproject.model.DeveloperAccount;
import com.github.andlyticsproject.sync.NotificationHandler;
import com.github.andlyticsproject.util.ChangelogBuilder;
import com.github.andlyticsproject.util.DetachableAsyncTask;
import com.github.andlyticsproject.util.Utils;
import com.google.api.client.googleapis.extensions.android.gms.auth.UserRecoverableAuthIOException;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class Main extends BaseActivity implements AdapterView.OnItemSelectedListener,
		SwipeRefreshLayout.OnRefreshListener, NavigationView.OnNavigationItemSelectedListener,
        View.OnClickListener {

	/** Key for latest version code preference. */
	private static final String LAST_VERSION_CODE_KEY = "last_version_code";

	public static final String TAG = Main.class.getSimpleName();

	/** Dialog constant. **/
	public static final int DIALOG_ABOUT_ID = 1;

	private boolean cancelRequested;
	private DrawerLayout mainDrawer;
    private NavigationView navigationView;
	private SwipeRefreshLayout swipeRefresh;
	private ListView mainListView;
	private TextView statusText;
	private MainListAdapter adapter;
	private View footer;

	private StatsMode currentStatsMode;
	private MenuItem statsModeMenuItem;

	private List<DeveloperAccount> developerAccounts;

	private DateFormat timeFormat = DateFormat.getTimeInstance(DateFormat.MEDIUM);

	private static final int REQUEST_OPEN_DOCUMENT = 88;
	private static final int REQUEST_CODE_MANAGE_ACCOUNTS = 99;

    private static class State {
		// TODO replace with loaders
		LoadDbEntries loadDbEntries;
		LoadRemoteEntries loadRemoteEntries;
		LoadIconInCache loadIconInCache;
		List<AppInfo> lastAppList;

		void detachAll() {
			if (loadDbEntries != null) {
				loadDbEntries.detach();
			}

			if (loadRemoteEntries != null) {
				loadRemoteEntries.detach();
			}

			if (loadIconInCache != null) {
				loadIconInCache.detach();
			}
		}

		void attachAll(Main activity) {
			if (loadDbEntries != null) {
				loadDbEntries.attach(activity);
			}

			if (loadRemoteEntries != null) {
				loadRemoteEntries.attach(activity);
			}

			if (loadIconInCache != null) {
				loadIconInCache.attach(activity);
			}
		}

		void setLoadDbEntries(LoadDbEntries task) {
			if (loadDbEntries != null) {
				loadDbEntries.detach();
			}
			loadDbEntries = task;
		}

		void setLoadRemoteEntries(LoadRemoteEntries task) {
			if (loadRemoteEntries != null) {
				loadRemoteEntries.detach();
			}
			loadRemoteEntries = task;
		}

		void setLoadIconInCache(LoadIconInCache task) {
			if (loadIconInCache != null) {
				loadIconInCache.detach();
			}
			loadIconInCache = task;
		}
	}

	private State state = new State();

	/** Called when the activity is first created. */
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

		LayoutInflater layoutInflater = getLayoutInflater();

		// setup Nav Drawer
		mainDrawer = (DrawerLayout) findViewById(R.id.drawer_layout);
        navigationView = (NavigationView) findViewById(R.id.navigation_view);
        navigationView.setNavigationItemSelectedListener(this);

		// setup toolbar
		Toolbar mainToolbar = (Toolbar) findViewById(R.id.main_toolbar);
		setSupportActionBar(mainToolbar);
		ActionBar ab = getSupportActionBar();
		ab.setHomeAsUpIndicator(R.drawable.icon_drawer_menu);
		ab.setDisplayHomeAsUpEnabled(true);
		mainToolbar.setBackgroundColor(getResources().getColor(R.color.lightBlue));

		// BaseActivity has already selected the account
		updateAccountsList();

		// setup swipeRefreshLayou
		swipeRefresh = (SwipeRefreshLayout) findViewById(R.id.swipeRefresh);
		swipeRefresh.setColorSchemeResources(R.color.lightBlue);
		swipeRefresh.setOnRefreshListener(this);

		// setup main list
		mainListView = (ListView) findViewById(R.id.main_app_list);
		mainListView.addHeaderView(layoutInflater.inflate(R.layout.main_list_header, null), null,
				false);
		footer = layoutInflater.inflate(R.layout.main_list_footer, null);
		footer.setVisibility(View.INVISIBLE);
		mainListView.addFooterView(footer, null, false);
		adapter = new MainListAdapter(this, accountName, currentStatsMode);
		mainListView.setAdapter(adapter);

		// status & progress bar
		statusText = (TextView) findViewById(R.id.main_app_status_line);

		currentStatsMode = Preferences.getStatsMode(this);
		updateStatsMode();

		State lastState = (State) getLastCustomNonConfigurationInstance();
		if (lastState != null) {
			state = lastState;
			state.attachAll(this);
			if (state.lastAppList != null) {
				adapter.setAppInfos(state.lastAppList);
				setSkipMainReload(true);
			}
		}

		// show changelog
		if (isUpdate()) {
			showChangelog();
		}
	}

	@Override
	public void onRefresh() {
		swipeRefresh.setEnabled(false);
		loadRemoteEntries();
	}

	@Override
	public void refreshStarted() {
		super.refreshStarted();
		if (!swipeRefresh.isRefreshing()) {
			swipeRefresh.setRefreshing(true);
			swipeRefresh.setEnabled(false);
		}
	}

	@Override
	public void refreshFinished() {
		super.refreshFinished();
		swipeRefresh.setRefreshing(false);
		swipeRefresh.setEnabled(true);
	}

    @Override
    public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
        switch (parent.getId()){
        case R.id.account_selector:
            if (!developerAccounts.get(position).getName().equals(accountName)) {
                // Only switch if it is a new account
                Intent intent = new Intent(this, Main.class);
                intent.putExtra(BaseActivity.EXTRA_AUTH_ACCOUNT_NAME,
                        developerAccounts.get(position).getName());
                startActivity(intent);
                overridePendingTransition(R.anim.activity_fade_in, R.anim.activity_fade_out);
                // Call finish to ensure we don't get multiple activities running
                finish();
            }
        }
    }

    @Override
    public void onNothingSelected(AdapterView<?> parent) {
        // Do Nothing
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()){
        case R.id.manage_accounts:
            Intent accountsIntent = new Intent(this, LoginActivity.class);
            accountsIntent.putExtra(LoginActivity.EXTRA_MANAGE_ACCOUNTS_MODE, true);
            startActivityForResult(accountsIntent, REQUEST_CODE_MANAGE_ACCOUNTS);
        }

    }

	@Override
	protected void onResume() {
		super.onResume();

		if (!isSkipMainReload() && shouldRemoteUpdateStats()) {
			loadLocalEntriesAndUpdate();
		} else {
			loadLocalEntriesOnly();
		}

		setSkipMainReload(false);

		AndlyticsApp.getInstance().setIsAppVisible(true);
	}

    @Override
    public boolean onNavigationItemSelected(MenuItem menuItem) {
        switch (menuItem.getItemId()){
        case R.id.itemMainmenuImport:
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                Intent openIntent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
                openIntent.setType("*/*");
                openIntent.putExtra(Intent.EXTRA_MIME_TYPES, new String[] { "application/zip" });
                //hidden
                openIntent.putExtra("android.content.extra.SHOW_ADVANCED", true);
                startActivityForResult(openIntent, REQUEST_OPEN_DOCUMENT);
            } else {
                File fileToImport = StatsCsvReaderWriter.getExportFileForAccount(accountName);
                if (!fileToImport.exists()) {
                    Toast.makeText(
                            this,
                            getString(R.string.import_no_stats_file, fileToImport.getAbsolutePath()),
                            Toast.LENGTH_LONG).show();
                    return true;
                }

                Intent importIntent = new Intent(this, ImportActivity.class);
                importIntent.setAction(Intent.ACTION_VIEW);
                importIntent.setData(Uri.fromFile(fileToImport));
                startActivity(importIntent);
            }
            break;
        case R.id.itemMainmenuExport:
            Intent exportIntent = new Intent(this, ExportActivity.class);
            exportIntent.putExtra(ExportActivity.EXTRA_ACCOUNT_NAME, accountName);
            startActivity(exportIntent);
            break;
        case R.id.itemMainmenuAbout:
            // launch about activity
            Intent aboutIntent = new Intent(this, AboutActivity.class);
            startActivity(aboutIntent);
            break;
        case R.id.itemMainmenuPreferences:
            Intent preferencesIntent = new Intent(this, AndlyticsPreferenceActivity.class);
            preferencesIntent.putExtra(BaseActivity.EXTRA_AUTH_ACCOUNT_NAME, accountName);
            startActivity(preferencesIntent);
            break;
        default:
            return false;
        }
        return true;
    }

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		menu.clear();
		getMenuInflater().inflate(R.menu.main_menu, menu);
		statsModeMenuItem = menu.findItem(R.id.itemMainmenuStatsMode);
		if (isRefreshing())
			menu.findItem(R.id.itemMainmenuRefresh).setActionView(
					R.layout.action_bar_indeterminate_progress);
		updateStatsMode();
		return true;
	}

	/**
	 * Called if item in option menu is selected.
	 * 
	 * @param item
	 * The chosen menu item
	 * @return boolean true/false
	 */
	@TargetApi(19)
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		switch (item.getItemId()) {
		case android.R.id.home:
			mainDrawer.openDrawer(GravityCompat.START);
			break;
		case R.id.itemMainmenuRefresh:
			loadRemoteEntries();
			break;
		case R.id.itemMainmenuStatsMode:
			if (currentStatsMode.equals(StatsMode.PERCENT)) {
				currentStatsMode = StatsMode.DAY_CHANGES;
			} else {
				currentStatsMode = StatsMode.PERCENT;
			}
			updateStatsMode();
			break;
		case R.id.itemMainmenuAccounts:
			Intent accountsIntent = new Intent(this, LoginActivity.class);
			accountsIntent.putExtra(LoginActivity.EXTRA_MANAGE_ACCOUNTS_MODE, true);
			startActivityForResult(accountsIntent, REQUEST_CODE_MANAGE_ACCOUNTS);
			break;
		default:
			return false;
		}
		return true;
	}

    @Override
    public void onBackPressed() {
        if (mainDrawer.isDrawerOpen(GravityCompat.START))
            mainDrawer.closeDrawer(GravityCompat.START);
        else
            super.onBackPressed();
    }

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		// NOTE startActivityForResult does not work when singleTask is set in
		// the manifiest
		// Therefore, FLAG_ACTIVITY_CLEAR_TOP is used on any intents instead.
		if (requestCode == REQUEST_CODE_MANAGE_ACCOUNTS) {
			if (resultCode == RESULT_OK) {
				// Went to manage accounts, didn't do anything to the current
				// account,
				// but might have added/removed other accounts
				updateAccountsList();
			} else if (resultCode == RESULT_CANCELED) {
				// The user removed the current account, remove it from
				// preferences and finish
				// so that the user has to choose an account when they next
				// start the app
				developerAccountManager.unselectDeveloperAccount();
				finish();
			}
		} else if (requestCode == REQUEST_AUTHENTICATE) {
			if (resultCode == RESULT_OK) {
				// user entered credentials, etc, try to get data again
				loadRemoteEntries();
			} else {
				Toast.makeText(this, getString(R.string.auth_error, accountName), Toast.LENGTH_LONG)
						.show();
			}
		} else if (requestCode == REQUEST_GOOGLE_PLAY_SERVICES) {
			if (resultCode == AppCompatActivity.RESULT_OK) {
			} else {
				checkGooglePlayServicesAvailable();
			}
		} else if (requestCode == REQUEST_AUTHORIZATION) {
			if (resultCode == AppCompatActivity.RESULT_OK) {
				loadRemoteEntries();
			} else {
				Toast.makeText(this, getString(R.string.account_authorization_denied, accountName),
						Toast.LENGTH_LONG).show();
			}
		} else if (requestCode == REQUEST_OPEN_DOCUMENT) {
			if (resultCode == RESULT_OK) {
				Intent importIntent = new Intent(this, ImportActivity.class);
				importIntent.setAction(Intent.ACTION_VIEW);
				importIntent.setData(data.getData());
				startActivity(importIntent);
			} else {
				Toast.makeText(
						this,
						getString(R.string.import_no_stats_file, data == null ? "" : data.getData()),
						Toast.LENGTH_LONG).show();
			}
		}
		super.onActivityResult(requestCode, resultCode, data);
	}

	@Override
	public Object onRetainCustomNonConfigurationInstance() {
		state.lastAppList = adapter.getAppInfos();
		state.detachAll();

		return state;
	}

	@Override
	protected void onPause() {
		super.onPause();
		AndlyticsApp.getInstance().setIsAppVisible(false);
	}

	@Override
	protected void onDestroy() {
		statsModeMenuItem = null;
		super.onDestroy();
	}

	private void updateAccountsList() {
		developerAccounts = developerAccountManager.getActiveDeveloperAccounts();
        Spinner accountSelector = (Spinner) navigationView.findViewById(R.id.account_selector);
        accountSelector.getBackground().setColorFilter(
                getResources().getColor(R.color.primary_material_light), PorterDuff.Mode.SRC_ATOP);
        AccountSelectorAdaper accountsAdapter = new AccountSelectorAdaper(this,
                R.layout.account_selector_item, developerAccounts);
        accountsAdapter.setDropDownViewResource(R.layout.spinner_dropdown_item);
        accountSelector.setAdapter(accountsAdapter);
        accountSelector.setOnItemSelectedListener(this);
        // Only use the spinner if we have multiple accounts
        accountSelector.setEnabled(developerAccounts.size() > 1);

		if (developerAccounts.size() > 1) {
			int selectedIndex = 0;
			int index = 0;
			for (DeveloperAccount account : developerAccounts) {
				if (account.getName().equals(accountName)) {
					selectedIndex = index;
				}
				index++;
			}
            accountSelector.setSelection(selectedIndex);
		}

        navigationView.findViewById(R.id.manage_accounts).setOnClickListener(this);
	}

	private void updateMainList(List<AppInfo> apps) {
		if (apps != null) {
			if (apps.size() > 0) {
				footer.setVisibility(View.VISIBLE);
			}

			adapter.setAppInfos(apps);
			adapter.notifyDataSetChanged();

			Date lastUpdateDate = null;

			for (int i = 0; i < apps.size(); i++) {
				Date dateObject = apps.get(i).getLastUpdate();
				if (lastUpdateDate == null || lastUpdateDate.before(dateObject)) {
					lastUpdateDate = dateObject;
				}
			}

			if (lastUpdateDate != null) {
				statusText.setText(Preferences.getDateFormatLong(this).format(lastUpdateDate) + " "
						+ timeFormat.format(lastUpdateDate));
			}
		}

		if (!swipeRefresh.isRefreshing()) {
			swipeRefresh.setRefreshing(false);
			swipeRefresh.setEnabled(true);
		}

        findViewById(R.id.main_app_list_loading).setVisibility(View.GONE);
	}

	private static class LoadRemoteEntries extends
			DetachableAsyncTask<String, Integer, Exception, Main> {

		private ContentAdapter db;

		public LoadRemoteEntries(Main activity) {
			super(activity);
			db = ContentAdapter.getInstance(activity.getApplication());
		}

		@Override
		protected void onPreExecute() {
			if (activity == null) {
				return;
			}

			activity.refreshStarted();
		}

		@SuppressLint("NewApi")
		@SuppressWarnings("unchecked")
		@Override
		protected Exception doInBackground(String... params) {
			if (activity == null) {
				return null;
			}

			Exception exception = null;

			List<AppInfo> appDownloadInfos = null;
			try {
				DevConsoleV2 v2 = DevConsoleRegistry.getInstance().get(activity.accountName);

				appDownloadInfos = v2.getAppInfo(activity);

				if (activity.cancelRequested) {
					activity.cancelRequested = false;
					return null;
				}

				Map<String, List<String>> admobAccountSiteMap = new HashMap<String, List<String>>();

				List<AppStatsDiff> diffs = new ArrayList<AppStatsDiff>();

				for (AppInfo appDownloadInfo : appDownloadInfos) {
					// update in database and check for diffs
					// sets DB ID of ApInfo
					diffs.add(db.insertOrUpdateStats(appDownloadInfo));
					String[] admobDetails = AndlyticsDb.getInstance(activity).getAdmobDetails(
							appDownloadInfo.getPackageName());
					if (admobDetails != null) {
						String admobAccount = admobDetails[0];
						String admobSiteId = admobDetails[1];
						String adUnitId = admobDetails[2];
						if (admobAccount != null && adUnitId == null) {
							List<String> siteList = admobAccountSiteMap.get(admobAccount);
							if (siteList == null) {
								siteList = new ArrayList<String>();
							}
							siteList.add(admobSiteId);
							admobAccountSiteMap.put(admobAccount, siteList);
						} else {
							List<String> siteList = admobAccountSiteMap.get(admobAccount);
							if (siteList == null) {
								siteList = new ArrayList<String>();
							}
							siteList.add(adUnitId);
							admobAccountSiteMap.put(admobAccount, siteList);
						}
					}
					// update app details
					AndlyticsDb.getInstance(activity).insertOrUpdateAppDetails(appDownloadInfo);
				}

				// check for notifications
				NotificationHandler.handleNotificaions(activity, diffs, activity.accountName);

				// sync admob accounts
				Set<String> admobAccuntKeySet = admobAccountSiteMap.keySet();
				for (String admobAccount : admobAccuntKeySet) {
					AdSenseClient.foregroundSyncStats(activity, admobAccount,
							admobAccountSiteMap.get(admobAccount));
				}

				activity.state.setLoadIconInCache(new LoadIconInCache(activity));
				Utils.execute(activity.state.loadIconInCache, appDownloadInfos);

			} catch (UserRecoverableAuthIOException userRecoverableException) {
				activity.startActivityForResult(userRecoverableException.getIntent(),
						REQUEST_AUTHORIZATION);
			} catch (Exception e) {
				// These exceptions can contain very long JSON strings
				// Explicitly print out the root cause first
				Log.e(TAG,
						"Error while requesting developer console : " + Utils.stackTraceToString(e));
				Log.e(TAG, "Error while requesting developer console : " + e.getMessage(), e);
				exception = e;
			}

			return exception;
		}

		@Override
		protected void onPostExecute(Exception exception) {
			if (activity == null) {
				return;
			}

			activity.refreshFinished();

			if (exception == null) {
				activity.developerAccountManager.saveLastStatsRemoteUpdateTime(
						activity.accountName, System.currentTimeMillis());
				activity.loadLocalEntriesOnly();
				return;
			}

			activity.handleUserVisibleException(exception);
			activity.loadLocalEntriesOnly();
		}

	}

	private void loadLocalEntriesOnly() {
		loadDbEntries(false);
	}

	private void loadLocalEntriesAndUpdate() {
		loadDbEntries(true);
	}

	private void loadDbEntries(boolean triggerRemoteCall) {
		state.setLoadDbEntries(new LoadDbEntries(this));
		Utils.execute(state.loadDbEntries, triggerRemoteCall);
	}

	private static class LoadDbEntries extends DetachableAsyncTask<Boolean, Void, Boolean, Main> {

		private ContentAdapter db;

		LoadDbEntries(Main activity) {
			super(activity);
			db = ContentAdapter.getInstance(activity.getApplication());
		}

		private List<AppInfo> allStats = new ArrayList<AppInfo>();
		private List<AppInfo> filteredStats = new ArrayList<AppInfo>();

		private Boolean triggerRemoteCall;

		@Override
		protected Boolean doInBackground(Boolean... params) {
			if (activity == null) {
				return null;
			}

			allStats = db.getAllAppsLatestStats(activity.accountName);

			for (AppInfo appInfo : allStats) {
				if (!appInfo.isGhost()) {
					if (appInfo.getAdmobSiteId() != null || appInfo.getAdmobAdUnitId() != null) {
						List<AdmobStats> admobStats = db.getAdmobStats(appInfo.getAdmobSiteId(),
								appInfo.getAdmobAdUnitId(), Timeframe.LAST_TWO_DAYS).getStats();
						if (admobStats.size() > 0) {
							AdmobStats admob = admobStats.get(admobStats.size() - 1);
							appInfo.setAdmobStats(admob);
						}
					}
					filteredStats.add(appInfo);
				}

			}

			triggerRemoteCall = params[0];

			return null;
		}

		@Override
		protected void onPostExecute(Boolean result) {
			if (activity == null) {
				return;
			}

			activity.updateMainList(filteredStats);

			if (triggerRemoteCall) {
				activity.loadRemoteEntries();
			} else {
				if (allStats.isEmpty()) {
					Toast.makeText(activity, R.string.no_published_apps, Toast.LENGTH_LONG).show();
				}
			}
		}

	}

	private static class LoadIconInCache extends
			DetachableAsyncTask<List<AppInfo>, Void, Boolean, Main> {

		LoadIconInCache(Main activity) {
			super(activity);
		}

		@Override
		protected Boolean doInBackground(List<AppInfo>... params) {
			if (activity == null) {
				return null;
			}

			List<AppInfo> appInfos = params[0];
			Boolean success = Boolean.FALSE;

			for (AppInfo appInfo : appInfos) {
				String iconUrl = appInfo.getIconUrl();

				if (iconUrl != null) {
					File iconFile = new File(activity.getCacheDir(), appInfo.getIconName());
					if (!iconFile.exists()) {
						try {
							if (iconFile.createNewFile()) {
								Utils.getAndSaveToFile(new URL(iconUrl), iconFile);

								success = Boolean.TRUE;
							}
						} catch (IOException e) {
							if (iconFile.exists()) {
								iconFile.delete();
							}

							Log.d("log_tag", "Error: " + e);
						}
					}
				}

			}

			return success;
		}

		@Override
		protected void onPostExecute(Boolean success) {
			if (activity == null) {
				return;
			}

			if (success) {
				activity.adapter.notifyDataSetChanged();
			}
		}

	}

	private void updateStatsMode() {
		if (statsModeMenuItem != null) {
			switch (currentStatsMode) {
			case PERCENT:
				statsModeMenuItem.setTitle(R.string.daily);
				statsModeMenuItem.setIcon(R.drawable.icon_plusminus);
				break;

			case DAY_CHANGES:
				statsModeMenuItem.setTitle(R.string.percentage);
				statsModeMenuItem.setIcon(R.drawable.icon_percent);
				break;

			default:
				break;
			}
		}
		adapter.setStatsMode(currentStatsMode);
		adapter.notifyDataSetChanged();
		Preferences.saveStatsMode(currentStatsMode, Main.this);
	}

	private void loadRemoteEntries() {
		state.setLoadRemoteEntries(new LoadRemoteEntries(this));
		Utils.execute(state.loadRemoteEntries);
	}

	/**
	 * checks if the app is started for the first time (after an update).
	 * 
	 * @return <code>true</code> if this is the first start (after an update)
	 * else <code>false</code>
	 */
	private boolean isUpdate() {
		// Get the versionCode of the Package, which must be different
		// (incremented) in each release on the market in the
		// AndroidManifest.xml
		final int versionCode = Utils.getActualVersionCode(this);

		final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
		final long lastVersionCode = prefs.getLong(LAST_VERSION_CODE_KEY, 0);

		// don't show popup on first install, creates weird interaction with 
		// authorization popup from GLS
		if (lastVersionCode == 0) {
			return false;
		}

		if (versionCode != lastVersionCode) {
			Log.i(TAG, "versionCode " + versionCode + " is different from the last known version "
					+ lastVersionCode);
			return true;
		} else {
			Log.i(TAG, "versionCode " + versionCode + " is already known");
			return false;
		}
	}

	private void showChangelog() {
		final int versionCode = Utils.getActualVersionCode(this);
		final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
		ChangelogBuilder.create(this, new Dialog.OnClickListener() {

			public void onClick(DialogInterface dialogInterface, int i) {
				// Mark this version as read
				sp.edit().putLong(LAST_VERSION_CODE_KEY, versionCode).commit();

				dialogInterface.dismiss();
			}
		}).show();
	}

	private static class AccountSelectorAdaper extends ArrayAdapter<DeveloperAccount> {
		private Context context;
		private List<DeveloperAccount> accounts;
		private int textViewResourceId;

		public AccountSelectorAdaper(Context context, int textViewResourceId,
				List<DeveloperAccount> objects) {
			super(context, textViewResourceId, objects);
			this.context = context;
			this.accounts = objects;
			this.textViewResourceId = textViewResourceId;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			View rowView = convertView;
			if (rowView == null) {
				LayoutInflater inflater = (LayoutInflater) context
						.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
				rowView = inflater.inflate(textViewResourceId, parent, false);
			}

			TextView subtitle = (TextView) rowView.findViewById(android.R.id.text1);
			subtitle.setText(accounts.get(position).getName());
			Resources res = context.getResources();
			if (res.getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
				// Scale the text down slightly to fit on landscape due to the
				// shorter Action Bar
				// and additional padding due to the drop down
				// We don't use predefined values as it saves duplicating all of
				// the different display
				// configuration values from the ABS library
				float px = subtitle.getTextSize() * 0.9f;
				subtitle.setTextSize(px / (res.getDisplayMetrics().densityDpi / 160f));

			}

			// TODO In the future when accounts linked to multiple developer
			// consoles are supported
			// we can either merge all the apps together, or extend this adapter
			// to let the user select
			// account/console E.g:
			// account1
			// account2/console1
			// account2/console2
			// ...

			return rowView;
		}

		@Override
		public View getDropDownView(int position, View convertView, ViewGroup parent) {
			View result = super.getDropDownView(position, convertView, parent);
			((TextView) result).setText(accounts.get(position).getName());

			return result;
		}

	}

}
