package com.pluscubed.plustimer.ui.solvelist;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.ShareCompat;
import com.couchbase.lite.CouchbaseLiteException;
import com.pluscubed.plustimer.R;
import com.pluscubed.plustimer.base.Presenter;
import com.pluscubed.plustimer.base.PresenterFactory;
import com.pluscubed.plustimer.base.RecyclerViewUpdate;
import com.pluscubed.plustimer.model.PuzzleType;
import com.pluscubed.plustimer.model.Session;
import com.pluscubed.plustimer.model.Solve;
import com.pluscubed.plustimer.utils.PrefUtils;
import com.pluscubed.plustimer.utils.SolveDialogUtils;
import java.io.IOException;
import java.util.Collections;
import rx.Observable;
import rx.SingleSubscriber;
import rx.android.schedulers.AndroidSchedulers;
public class SolveListPresenter extends Presenter<SolveListView> {
public static final String INIT_SESSION_ID = "history_session";
public static final String INIT_PUZZLETYPE_ID = "history_puzzletype";
private static final String INIT_CURRENT = "current";
private final Session.SolvesListener mSessionSolvesListener;
private final PuzzleType.CurrentSessionChangeListener mPuzzleTypeCurrentChangeListener;
private String mPuzzleTypeId;
private String mSessionId;
private boolean mIsCurrent;
private boolean mInitialized;
private boolean mViewInitialized;
public SolveListPresenter(Bundle arguments) {
mIsCurrent = arguments.getBoolean(INIT_CURRENT);
mPuzzleTypeId = arguments.getString(INIT_PUZZLETYPE_ID);
mSessionId = arguments.getString(INIT_SESSION_ID);
mSessionSolvesListener = (update, solve) -> {
updateView();
updateAdapter(update, solve);
};
mPuzzleTypeCurrentChangeListener = oldType -> {
if (!isViewAttached()) {
return;
}
removeSessionSolvesListener(oldType);
//noinspection ConstantConditions
PuzzleType.getCurrent(getView().getContextCompat())
.map(PuzzleType::getCurrentSessionId)
.subscribe(currentSession -> {
mPuzzleTypeId = PuzzleType.getCurrentId(getView().getContextCompat());
mSessionId = currentSession;
reloadSolveList();
updateView();
attachSessionSolvesListener(getView());
});
};
if (mIsCurrent)
PuzzleType.addCurrentChangeListener(mPuzzleTypeCurrentChangeListener);
}
public static SolveListFragment newInstance(boolean current) {
return newInstance(current, "", "");
}
public static SolveListFragment newInstance(boolean current, String puzzleTypeId, String sessionId) {
Bundle args = new Bundle();
args.putBoolean(INIT_CURRENT, current);
args.putString(INIT_PUZZLETYPE_ID, puzzleTypeId);
args.putString(INIT_SESSION_ID, sessionId);
SolveListFragment fragment = new SolveListFragment();
fragment.setArguments(args);
return fragment;
}
@Override
public void onViewAttached(SolveListView view) {
super.onViewAttached(view);
if (mIsCurrent) {
PuzzleType.getCurrent(view.getContextCompat())
.map(PuzzleType::getCurrentSessionId)
.subscribe(currentSession -> {
initializeView(PuzzleType.getCurrentId(view.getContextCompat()), currentSession);
});
} else if (mPuzzleTypeId != null && mSessionId != null) {
initializeView(mPuzzleTypeId, mSessionId);
} else {
throw new RuntimeException("Must be current or have specified puzzletype and session");
}
view.getSolveListAdapter().updateSignAndMillisecondsMode();
if (!mInitialized) {
attachSessionSolvesListener(getView());
mInitialized = true;
}
}
@Override
public void onViewDetached() {
super.onViewDetached();
mViewInitialized = false;
}
@SuppressWarnings("ConstantConditions")
private void attachSessionSolvesListener(SolveListView view) {
if (!isViewAttached()) {
return;
}
PuzzleType.getCurrent(view.getContextCompat())
.flatMap(puzzleType -> puzzleType.getCurrentSessionDeferred(getView().getContextCompat()))
.subscribe(session -> {
session.addListener(mSessionSolvesListener);
});
}
@SuppressWarnings("ConstantConditions")
private void removeSessionSolvesListener(String puzzleTypeId) {
if (!isViewAttached()) {
return;
}
String id = puzzleTypeId == null ? PuzzleType.getCurrentId(getView().getContextCompat()) : puzzleTypeId;
PuzzleType.get(getView().getContextCompat(), id)
.flatMap(puzzleType -> puzzleType.getCurrentSessionDeferred(getView().getContextCompat()))
.subscribe(session -> {
session.removeListener(mSessionSolvesListener);
});
}
public void initializeView(String puzzleTypeId, String sessionId) {
mPuzzleTypeId = puzzleTypeId;
mSessionId = sessionId;
if (!isViewAttached()) {
return;
}
//noinspection ConstantConditions
if (!getView().getSolveListAdapter().isInitialized()) {
reloadSolveList();
}
if (!mViewInitialized) {
//noinspection ConstantConditions
getView().setInitialized();
updateView();
mViewInitialized = true;
}
}
private void reloadSolveList() {
PuzzleType.get(getView().getContextCompat(), mPuzzleTypeId)
.flatMap(puzzleType -> puzzleType.getSessionDeferred(getView().getContextCompat(), mSessionId))
.flatMapObservable(session ->
session.getSortedSolves(getView().getContextCompat())).toList()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(solves -> {
Collections.reverse(solves);
getView().getSolveListAdapter().setSolves(mPuzzleTypeId, solves);
updateAdapter(RecyclerViewUpdate.DATA_RESET, null);
});
}
@Override
public void onDestroyed() {
removeSessionSolvesListener(null);
if (mIsCurrent)
PuzzleType.removeCurrentChangeListener(mPuzzleTypeCurrentChangeListener);
}
public void onResetButtonClicked() {
if (isViewAttached()) {
//noinspection ConstantConditions
getView().showResetWarningDialog();
}
}
@SuppressWarnings("ConstantConditions")
public void onResetDialogConfirmed() {
if (isViewAttached()) {
PuzzleType.get(getView().getContextCompat(), mPuzzleTypeId)
.flatMap(puzzleType -> puzzleType.getCurrentSessionDeferred(getView().getContextCompat()))
.subscribe(new SingleSubscriber<Session>() {
@Override
public void onSuccess(Session session) {
session.reset(getView().getContextCompat());
}
@Override
public void onError(Throwable error) {
}
});
//noinspection ConstantConditions
getView().showSessionResetSnackbar();
}
}
@SuppressWarnings("ConstantConditions")
public void onSubmitClicked() {
if (isViewAttached()) {
PuzzleType.get(getView().getContextCompat(), mPuzzleTypeId)
.flatMapObservable(puzzleType -> Observable.fromCallable(() -> {
puzzleType.submitCurrentSession(getView().getContextCompat());
return null;
}))
.subscribe();
getView().showSessionSubmittedSnackbar();
}
}
@SuppressWarnings("ConstantConditions")
public void onAddSolvePressed() {
if (isViewAttached()) {
SolveDialogUtils.createSolveDialog(getView().getContextCompat(), true, mPuzzleTypeId, mSessionId, null);
}
}
@SuppressWarnings("ConstantConditions")
private void updateView() {
if (!isViewAttached()) {
return;
}
PuzzleType.get(getView().getContextCompat(), mPuzzleTypeId)
.flatMap(puzzleType -> puzzleType.getSessionDeferred(getView().getContextCompat(), mSessionId))
.observeOn(AndroidSchedulers.mainThread())
.subscribe(session -> {
int numberOfSolves = session.getNumberOfSolves();
if (numberOfSolves <= 0) {
if (mIsCurrent) {
getView().enableResetSubmitButtons(false);
} else {
deleteSession();
return;
}
getView().showList(false);
} else {
if (mIsCurrent) {
getView().enableResetSubmitButtons(true);
}
getView().showList(true);
}
});
}
private void deleteSession() {
PuzzleType.get(getView().getContextCompat(), mPuzzleTypeId)
.subscribe(puzzleType -> {
try {
puzzleType.deleteSession(getView().getContextCompat(), mSessionId);
} catch (CouchbaseLiteException | IOException e) {
e.printStackTrace();
}
});
if (isViewAttached())
getView().getContextCompat().finish();
}
public void onSharePressed() {
if (!isViewAttached()) {
return;
}
//noinspection ConstantConditions
Context context = getView().getContextCompat();
PuzzleType.get(context, mPuzzleTypeId)
.flatMap(puzzleType -> puzzleType.getSessionDeferred(context, mSessionId))
.flatMap(session ->
session.getStatsDeferred(context,
mPuzzleTypeId,
mIsCurrent,
true,
PrefUtils.isDisplayMillisecondsEnabled(context),
PrefUtils.isSignEnabled(context)
))
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new SingleSubscriber<String>() {
@Override
public void onSuccess(String statsString) {
Intent intent = ShareCompat.IntentBuilder.from(getView().getContextCompat())
.setType("text/plain")
.setText(statsString)
.setChooserTitle(R.string.share_dialog_title)
.createChooserIntent();
context.startActivity(intent);
}
@Override
public void onError(Throwable error) {
}
});
}
public void onSolveClicked(Solve solve) {
if (!isViewAttached()) {
return;
}
//noinspection ConstantConditions
SolveDialogUtils.createSolveDialog(
getView().getContextCompat(),
false,
mPuzzleTypeId,
mSessionId,
solve
);
}
@SuppressWarnings("ConstantConditions")
private void updateAdapter(RecyclerViewUpdate change, Solve solve) {
if (!isViewAttached()) {
return;
}
Activity context = getView().getContextCompat();
PuzzleType.get(context, mPuzzleTypeId)
.flatMap(puzzleType -> puzzleType.getSessionDeferred(context, mSessionId))
.flatMap(session -> session.getStatsDeferred(context,
mPuzzleTypeId,
mIsCurrent,
false,
PrefUtils.isDisplayMillisecondsEnabled(context),
PrefUtils.isSignEnabled(context)
))
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new SingleSubscriber<String>() {
@Override
public void onSuccess(String stats) {
getView().getSolveListAdapter().notifyChange(change, solve, stats);
}
@Override
public void onError(Throwable error) {
}
});
}
public void onDeletePressed() {
deleteSession();
}
public static class Factory implements PresenterFactory<SolveListPresenter> {
private Bundle arguments;
public Factory(Bundle bundle) {
arguments = bundle;
}
@Override
public SolveListPresenter create() {
return new SolveListPresenter(arguments);
}
}
}