package co.smartreceipts.android.trips;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabaseCorruptException;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
import javax.inject.Inject;
import co.smartreceipts.android.R;
import co.smartreceipts.android.activities.NavigationHandler;
import co.smartreceipts.android.adapters.TripCardAdapter;
import co.smartreceipts.android.analytics.Analytics;
import co.smartreceipts.android.analytics.events.Events;
import co.smartreceipts.android.fragments.WBListFragment;
import co.smartreceipts.android.model.Trip;
import co.smartreceipts.android.persistence.LastTripController;
import co.smartreceipts.android.persistence.database.controllers.TableEventsListener;
import co.smartreceipts.android.persistence.database.controllers.impl.TripTableController;
import co.smartreceipts.android.persistence.database.operations.DatabaseOperationMetadata;
import co.smartreceipts.android.rating.FeedbackDialogFragment;
import co.smartreceipts.android.rating.RatingDialogFragment;
import co.smartreceipts.android.receipts.ReceiptsFragment;
import co.smartreceipts.android.settings.UserPreferenceManager;
import co.smartreceipts.android.sync.BackupProvidersManager;
import co.smartreceipts.android.utils.cache.FragmentStateCache;
import co.smartreceipts.android.utils.log.Logger;
import co.smartreceipts.android.widget.Tooltip;
import co.smartreceipts.android.workers.EmailAssistant;
import dagger.android.support.AndroidSupportInjection;
import wb.android.dialog.BetterDialogBuilder;
import wb.android.flex.Flex;
public class TripFragment extends WBListFragment implements TableEventsListener<Trip>, AdapterView.OnItemLongClickListener {
public static final String ARG_NAVIGATE_TO_VIEW_LAST_TRIP = "arg_nav_to_last_trip";
private static final String OUT_NAV_TO_LAST_TRIP = "out_nav_to_last_trip";
@Inject
Flex flex;
@Inject
Analytics analytics;
@Inject
TripTableController tripTableController;
@Inject
BackupProvidersManager backupProvidersManager;
@Inject
UserPreferenceManager preferenceManager;
@Inject
FragmentStateCache fragmentStateCache;
@Inject
NavigationHandler navigationHandler;
@Inject
TripFragmentPresenter presenter;
private TripCardAdapter tripCardAdapter;
private ProgressBar progressBar;
private TextView noDataAlert;
private Tooltip tooltip;
private boolean navigateToLastTrip;
public static TripFragment newInstance() {
return new TripFragment();
}
@Override
public void onAttach(Context context) {
AndroidSupportInjection.inject(this);
super.onAttach(context);
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Logger.debug(this, "onCreate");
tripCardAdapter = new TripCardAdapter(getActivity(), preferenceManager, backupProvidersManager);
if (savedInstanceState == null) {
navigateToLastTrip = getArguments().getBoolean(ARG_NAVIGATE_TO_VIEW_LAST_TRIP);
} else {
navigateToLastTrip = savedInstanceState.getBoolean(OUT_NAV_TO_LAST_TRIP);
}
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Logger.debug(this, "onCreateView");
final View rootView = inflater.inflate(R.layout.trip_fragment_layout, container, false);
progressBar = (ProgressBar) rootView.findViewById(R.id.progress);
noDataAlert = (TextView) rootView.findViewById(R.id.no_data);
tooltip = (Tooltip) rootView.findViewById(R.id.trip_tooltip);
rootView.findViewById(R.id.trip_action_new).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tripMenu(null);
}
});
return rootView;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
setListAdapter(tripCardAdapter); // Set this here to ensure this has been laid out already
getListView().setOnItemLongClickListener(this);
final Toolbar toolbar = (Toolbar) getActivity().findViewById(R.id.toolbar);
if (toolbar != null) {
((AppCompatActivity) getActivity()).setSupportActionBar(toolbar);
}
presenter.checkRating();
}
@Override
public void onResume() {
super.onResume();
Logger.debug(this, "onResume");
tripTableController.subscribe(this);
tripTableController.get();
getActivity().setTitle(getFlexString(R.string.sr_app_name));
final ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
getSupportActionBar().setSubtitle(null);
}
}
@Override
public void onPause() {
Logger.debug(this, "onPause");
tripTableController.unsubscribe(this);
super.onPause();
}
@Override
public void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Logger.debug(this, "onSaveInstanceState");
outState.putBoolean(OUT_NAV_TO_LAST_TRIP, navigateToLastTrip);
}
@Override
public void onDestroy() {
fragmentStateCache.onDestroy(this);
super.onDestroy();
}
public final void tripMenu(final Trip trip) {
if (!presenter.isExternalStorage()) {
Toast.makeText(getActivity(), getFlexString(R.string.SD_ERROR), Toast.LENGTH_LONG).show();
return;
}
if (trip == null) {
navigationHandler.navigateToCreateTripFragment();
} else {
navigationHandler.navigateToEditTripFragment(trip);
}
}
public final boolean editTrip(final Trip trip) {
final BetterDialogBuilder builder = new BetterDialogBuilder(getActivity());
final String[] editTripItems = flex.getStringArray(getActivity(), R.array.EDIT_TRIP_ITEMS);
builder.setTitle(trip.getName())
.setCancelable(true)
.setNegativeButton(android.R.string.cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
})
.setItems(editTripItems, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int item) {
final String selection = editTripItems[item];
if (selection == editTripItems[0]) {
TripFragment.this.tripMenu(trip);
} else if (selection == editTripItems[1]) {
TripFragment.this.deleteTrip(trip);
}
dialog.cancel();
}
}).show();
return true;
}
public final void deleteTrip(final Trip trip) {
final BetterDialogBuilder builder = new BetterDialogBuilder(getActivity());
builder.setTitle(getString(R.string.delete_item, trip.getName()))
.setMessage(getString(R.string.delete_sync_information))
.setCancelable(true)
.setPositiveButton(getFlexString(R.string.DIALOG_TRIP_DELETE_POSITIVE_BUTTON), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
tripTableController.delete(trip, new DatabaseOperationMetadata());
}
})
.setNegativeButton(getFlexString(R.string.DIALOG_CANCEL), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int id) {
dialog.cancel();
}
}).show();
}
@Override
public void onListItemClick(ListView l, View v, int position, long id) {
viewReceipts(tripCardAdapter.getItem(position));
// v.setSelected(true);
}
@Override
public boolean onItemLongClick(AdapterView<?> a, View v, int position, long id) {
editTrip(tripCardAdapter.getItem(position));
return true;
}
@Override
public void onGetSuccess(@NonNull List<Trip> trips) {
if (isResumed()) {
progressBar.setVisibility(View.GONE);
getListView().setVisibility(View.VISIBLE);
if (trips.isEmpty()) {
noDataAlert.setVisibility(View.VISIBLE);
} else {
noDataAlert.setVisibility(View.INVISIBLE);
}
tripCardAdapter.notifyDataSetChanged(trips);
if (!trips.isEmpty() && navigateToLastTrip) {
navigateToLastTrip = false;
// If we have trips, open up whatever one was last used
final LastTripController lastTripController = new LastTripController(getActivity());
final Trip lastTrip = lastTripController.getLastTrip(trips);
if (lastTrip != null) {
viewReceipts(lastTrip);
}
}
}
}
@Override
public void onGetFailure(@Nullable Throwable e) {
if (isResumed()) {
if (e instanceof SQLiteDatabaseCorruptException) {
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setTitle(R.string.dialog_sql_corrupt_title).setMessage(R.string.dialog_sql_corrupt_message).setPositiveButton(R.string.dialog_sql_corrupt_positive, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int position) {
Intent intent = EmailAssistant.getEmailDeveloperIntent(getString(R.string.dialog_sql_corrupt_intent_subject), getString(R.string.dialog_sql_corrupt_intent_text));
getActivity().startActivity(Intent.createChooser(intent, getResources().getString(R.string.dialog_sql_corrupt_chooser)));
dialog.dismiss();
}
}).show();
} else {
Toast.makeText(getActivity(), R.string.database_get_error, Toast.LENGTH_LONG).show();
}
}
}
@Override
public void onInsertSuccess(@NonNull Trip trip, @NonNull DatabaseOperationMetadata databaseOperationMetadata) {
if (isResumed()) {
viewReceipts(trip);
}
}
@Override
public void onInsertFailure(@NonNull Trip trip, @Nullable Throwable ex, @NonNull DatabaseOperationMetadata databaseOperationMetadata) {
if (isAdded()) {
if (ex != null) {
Toast.makeText(getActivity(), R.string.toast_error_trip_exists, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getActivity(), getFlexString(R.string.database_error), Toast.LENGTH_LONG).show();
}
}
}
@Override
public void onUpdateSuccess(@NonNull Trip oldTip, @NonNull Trip newTrip, @NonNull DatabaseOperationMetadata databaseOperationMetadata) {
if (isResumed()) {
viewReceipts(newTrip);
}
}
@Override
public void onUpdateFailure(@NonNull Trip oldTrip, @Nullable Throwable ex, @NonNull DatabaseOperationMetadata databaseOperationMetadata) {
if (isAdded()) {
if (ex != null) {
Toast.makeText(getActivity(), R.string.toast_error_trip_exists, Toast.LENGTH_LONG).show();
} else {
Toast.makeText(getActivity(), getFlexString(R.string.database_error), Toast.LENGTH_LONG).show();
}
}
}
@Override
public void onDeleteSuccess(@NonNull Trip oldTrip, @NonNull DatabaseOperationMetadata databaseOperationMetadata) {
if (isAdded()) {
final Fragment detailsFragment = getFragmentManager().findFragmentByTag(ReceiptsFragment.TAG);
if (detailsFragment != null) {
getFragmentManager().beginTransaction().remove(detailsFragment).commit();
final ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setTitle(getFlexString(R.string.sr_app_name));
}
}
}
tripTableController.get();
}
@Override
public void onDeleteFailure(@NonNull Trip oldTrip, @Nullable Throwable e, @NonNull DatabaseOperationMetadata databaseOperationMetadata) {
if (isAdded()) {
Toast.makeText(getActivity(), getFlexString(R.string.database_error), Toast.LENGTH_LONG).show();
}
}
private void viewReceipts(Trip trip) {
navigationHandler.navigateToReportInfoFragment(trip);
}
public void showRatingTooltip() {
tooltip.setQuestion(R.string.rating_tooltip_text, new View.OnClickListener() {
@Override
public void onClick(View view) {
analytics.record(Events.Ratings.UserDeclinedRatingPrompt);
navigationHandler.showDialog(new FeedbackDialogFragment());
tooltip.hideWithAnimation();
presenter.dontShowRatingPrompt();
}
}, new View.OnClickListener() {
@Override
public void onClick(View view) {
analytics.record(Events.Ratings.UserAcceptedRatingPrompt);
navigationHandler.showDialog(new RatingDialogFragment());
tooltip.hideWithAnimation();
presenter.dontShowRatingPrompt();
}
});
tooltip.showWithAnimation();
analytics.record(Events.Ratings.RatingPromptShown);
}
private String getFlexString(int id){
return getFlexString(flex, id);
}
}