package co.smartreceipts.android.activities;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.os.Build;
import android.support.annotation.AnimRes;
import android.support.annotation.IdRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.widget.Toast;
import com.google.common.base.Preconditions;
import java.io.File;
import java.lang.ref.WeakReference;
import javax.inject.Inject;
import co.smartreceipts.android.R;
import co.smartreceipts.android.di.scopes.ActivityScope;
import co.smartreceipts.android.model.Receipt;
import co.smartreceipts.android.model.Trip;
import co.smartreceipts.android.ocr.apis.model.OcrResponse;
import co.smartreceipts.android.settings.widget.PreferenceHeaderReportOutputFragment;
import co.smartreceipts.android.settings.widget.SettingsActivity;
import co.smartreceipts.android.utils.IntentUtils;
import co.smartreceipts.android.utils.log.Logger;
import static android.preference.PreferenceActivity.EXTRA_SHOW_FRAGMENT;
@ActivityScope
public class NavigationHandler<T extends FragmentActivity> {
private static final int DO_NOT_ANIM = 0;
private static final int MISSING_RES_ID = -1;
private final FragmentManager fragmentManager;
private final FragmentProvider fragmentProvider;
private final WeakReference<FragmentActivity> fragmentActivityWeakReference;
private final boolean isDualPane;
@Inject
public NavigationHandler(T fragmentActivity, FragmentProvider fragmentProvider) {
fragmentActivityWeakReference = new WeakReference<>(Preconditions.checkNotNull(fragmentActivity));
fragmentManager = Preconditions.checkNotNull(fragmentActivity.getSupportFragmentManager());
this.fragmentProvider = Preconditions.checkNotNull(fragmentProvider);
isDualPane = Preconditions.checkNotNull(fragmentActivity.getResources().getBoolean(R.bool.isTablet));
}
public void navigateToHomeTripsFragment() {
replaceFragment(fragmentProvider.newTripFragmentInstance(true), R.id.content_list);
}
public void navigateUpToTripsFragment() {
replaceFragment(fragmentProvider.newTripFragmentInstance(false), R.id.content_list);
}
public void navigateToReportInfoFragment(@NonNull Trip trip) {
if (isDualPane) {
replaceFragment(fragmentProvider.newReportInfoFragment(trip), R.id.content_details);
} else {
replaceFragment(fragmentProvider.newReportInfoFragment(trip), R.id.content_list);
}
}
public void navigateToReportInfoFragmentWithoutBackStack(@NonNull Trip trip) {
fragmentManager.popBackStackImmediate();
navigateToReportInfoFragment(trip);
}
public void navigateToCreateNewReceiptFragment(@NonNull Trip trip, @Nullable File file, @Nullable OcrResponse ocrResponse) {
if (isDualPane) {
replaceFragmentWithAnimation(fragmentProvider.newCreateReceiptFragment(trip, file, ocrResponse), R.id.content_details, R.anim.enter_from_bottom, DO_NOT_ANIM);
} else {
replaceFragmentWithAnimation(fragmentProvider.newCreateReceiptFragment(trip, file, ocrResponse), R.id.content_list, R.anim.enter_from_bottom, DO_NOT_ANIM);
}
}
public void navigateToEditReceiptFragment(@NonNull Trip trip, @NonNull Receipt receiptToEdit) {
if (isDualPane) {
replaceFragment(fragmentProvider.newEditReceiptFragment(trip, receiptToEdit), R.id.content_details);
} else {
replaceFragment(fragmentProvider.newEditReceiptFragment(trip, receiptToEdit), R.id.content_list);
}
}
public void navigateToCreateTripFragment() {
if (isDualPane) {
replaceFragmentWithAnimation(fragmentProvider.newCreateTripFragment(), R.id.content_details, R.anim.enter_from_bottom, DO_NOT_ANIM);
} else {
replaceFragmentWithAnimation(fragmentProvider.newCreateTripFragment(), R.id.content_list, R.anim.enter_from_bottom, DO_NOT_ANIM);
}
}
public void navigateToEditTripFragment(@NonNull Trip tripToEdit) {
if (isDualPane) {
replaceFragment(fragmentProvider.newEditTripFragment(tripToEdit), R.id.content_details);
} else {
replaceFragment(fragmentProvider.newEditTripFragment(tripToEdit), R.id.content_list);
}
}
public void navigateToOcrConfigurationFragment() {
if (isDualPane) {
replaceFragment(fragmentProvider.newOcrConfigurationFragment(), R.id.content_details);
} else {
replaceFragment(fragmentProvider.newOcrConfigurationFragment(), R.id.content_list);
}
}
public void navigateToViewReceiptImage(@NonNull Receipt receipt) {
if (isDualPane) {
replaceFragment(fragmentProvider.newReceiptImageFragment(receipt), R.id.content_details);
} else {
replaceFragment(fragmentProvider.newReceiptImageFragment(receipt), R.id.content_list);
}
}
public void navigateToViewReceiptPdf(@NonNull Receipt receipt) {
final FragmentActivity activity = fragmentActivityWeakReference.get();
if (activity != null && receipt.getFile() != null) {
try {
final Intent intent;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Logger.debug(this, "Creating a PDF view intent with a content scheme");
intent = IntentUtils.getViewIntent(activity, receipt.getFile(), "application/pdf");
} else {
Logger.debug(this, "Creating a PDF view intent with a file scheme");
intent = IntentUtils.getLegacyViewIntent(activity, receipt.getFile(), "application/pdf");
}
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
activity.startActivity(intent);
} catch (ActivityNotFoundException e) {
Toast.makeText(activity, R.string.error_no_pdf_activity_viewer, Toast.LENGTH_LONG).show();
}
}
}
public void navigateToBackupMenu() {
if (isDualPane) {
replaceFragment(fragmentProvider.newBackupsFragment(), R.id.content_details);
} else {
replaceFragment(fragmentProvider.newBackupsFragment(), R.id.content_list);
}
}
public void navigateToLoginScreen() {
if (isDualPane) {
replaceFragment(fragmentProvider.newLoginFragment(), R.id.content_details);
} else {
replaceFragment(fragmentProvider.newLoginFragment(), R.id.content_list);
}
}
public void navigateToSettings() {
final FragmentActivity activity = fragmentActivityWeakReference.get();
if (activity != null) {
final Intent intent = new Intent(activity, SettingsActivity.class);
activity.startActivity(intent);
}
}
public void navigateToSettingsScrollToReportSection() {
final FragmentActivity activity = fragmentActivityWeakReference.get();
if (activity != null) {
final Intent intent = new Intent(activity, SettingsActivity.class);
if (isDualPane) {
intent.putExtra(EXTRA_SHOW_FRAGMENT, PreferenceHeaderReportOutputFragment.class.getName());
} else {
intent.putExtra(SettingsActivity.EXTRA_GO_TO_CATEGORY, R.string.pref_output_header_key);
}
activity.startActivity(intent);
}
}
public boolean navigateBack() {
try {
return fragmentManager.popBackStackImmediate();
} catch (final IllegalStateException e) {
// This exception is always thrown if saveInstanceState was already been called.
return false;
}
}
public boolean navigateBackDelayed() {
try {
fragmentManager.popBackStack();
return true;
} catch (final IllegalStateException e) {
// This exception is always thrown if saveInstanceState was already been called.
return false;
}
}
public void showDialog(@NonNull DialogFragment dialogFragment) {
final String tag = dialogFragment.getClass().getName();
try {
dialogFragment.show(fragmentManager, tag);
} catch (IllegalStateException e) {
// This exception is always thrown if saveInstanceState was already been called.
}
}
public boolean isDualPane() {
return isDualPane;
}
public boolean shouldFinishOnBackNaviagtion() {
return fragmentManager.getBackStackEntryCount() == 1;
}
private void replaceFragment(@NonNull Fragment fragment, @IdRes int layoutResId) {
replaceFragmentWithAnimation(fragment, layoutResId, MISSING_RES_ID, MISSING_RES_ID);
}
private void replaceFragmentWithAnimation(@NonNull Fragment fragment, @IdRes int layoutResId, @AnimRes int enterAnimId, @AnimRes int exitAnimId) {
final String tag = fragment.getClass().getName();
boolean wasFragmentPopped;
try {
wasFragmentPopped = fragmentManager.popBackStackImmediate(tag, 0);
} catch (final IllegalStateException e) {
// This exception is always thrown if saveInstanceState was already been called.
wasFragmentPopped = false;
}
if (!wasFragmentPopped) {
final FragmentTransaction transaction = fragmentManager.beginTransaction();
if (enterAnimId >= 0 && exitAnimId >= 0) {
transaction.setCustomAnimations(enterAnimId, exitAnimId);
}
transaction.replace(layoutResId, fragment, tag)
.addToBackStack(tag)
.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
.commit();
}
}
}