package org.mtransit.android.ui;

import java.lang.ref.WeakReference;

import org.mtransit.android.commons.MTLog;
import org.mtransit.android.commons.TaskUtils;
import org.mtransit.android.commons.task.MTAsyncTask;
import org.mtransit.android.ui.fragment.MTDialogFragmentV4;

import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.common.api.GoogleApiClient;

public abstract class MTActivityWithGoogleAPIClient extends MTAppCompatActivity implements GoogleApiClient.ConnectionCallbacks,
		GoogleApiClient.OnConnectionFailedListener {

	private static final int REQUEST_RESOLVE_ERROR = 1001;
	private static final String DIALOG_ERROR = "dialog_error";
	private static final String STATE_RESOLVING_ERROR = "resolving_error";

	private boolean resolvingError = false;
	private boolean useGooglePlayServices = false;
	private GoogleApiClient googleApiClient;

	public MTActivityWithGoogleAPIClient(boolean useGooglePlayServices) {
		this.useGooglePlayServices = useGooglePlayServices;
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		this.resolvingError = savedInstanceState != null && savedInstanceState.getBoolean(STATE_RESOLVING_ERROR, false);
	}

	public GoogleApiClient getGoogleApiClientOrNull() {
		return this.googleApiClient;
	}

	public GoogleApiClient getGoogleApiClientOrInit() {
		if (this.useGooglePlayServices && this.googleApiClient == null) {
			initGoogleApiClient();
		}
		return this.googleApiClient;
	}

	private synchronized void initGoogleApiClient() {
		if (this.googleApiClient != null) {
			return;
		}
		GoogleApiClient.Builder googleApiClientBuilder = new GoogleApiClient.Builder(this);
		addGoogleAPIs(googleApiClientBuilder);
		googleApiClientBuilder //
				.addConnectionCallbacks(this)//
				.addOnConnectionFailedListener(this);
		this.googleApiClient = googleApiClientBuilder.build();
	}

	protected abstract void addGoogleAPIs(GoogleApiClient.Builder googleApiClientBuilder);

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		outState.putBoolean(STATE_RESOLVING_ERROR, this.resolvingError);
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		switch (requestCode) {
		case REQUEST_RESOLVE_ERROR:
			switch (resultCode) {
			case Activity.RESULT_OK:
				GoogleApiClient googleApiClient = getGoogleApiClientOrInit();
				if (googleApiClient != null && !googleApiClient.isConnecting() && !googleApiClient.isConnected()) {
					googleApiClient.connect();
				}
				break;
			default:
				MTLog.w(this, "Unexpected artivity result code '%s'.", resultCode);
			}
			break;
		default:
			MTLog.w(this, "Unexpected artivity request code '%s'.", requestCode);
		}
	}

	@Override
	protected void onStart() {
		super.onStart();
		if (!this.resolvingError) {
			TaskUtils.execute(new StartGoogleApiClientTask(this));
		}
	}

	private static class StartGoogleApiClientTask extends MTAsyncTask<Void, Void, Void> {

		private static final String TAG = MTActivityWithGoogleAPIClient.class.getSimpleName() + ">" + StartGoogleApiClientTask.class.getSimpleName();

		@Override
		public String getLogTag() {
			return TAG;
		}

		private WeakReference<MTActivityWithGoogleAPIClient> activityWR;

		public StartGoogleApiClientTask(MTActivityWithGoogleAPIClient activity) {
			this.activityWR = new WeakReference<MTActivityWithGoogleAPIClient>(activity);
		}

		@Override
		protected Void doInBackgroundMT(Void... params) {
			MTActivityWithGoogleAPIClient activity = this.activityWR == null ? null : this.activityWR.get();
			if (activity == null) {
				return null;
			}
			GoogleApiClient googleApiClient = activity.getGoogleApiClientOrInit();
			if (googleApiClient != null) {
				googleApiClient.connect();
			}
			return null;
		}
	}

	@Override
	protected void onStop() {
		super.onStop();
		TaskUtils.execute(new StopGoogleApiClientTask(this));
	}

	private static class StopGoogleApiClientTask extends MTAsyncTask<Void, Void, Void> {

		private static final String TAG = MTActivityWithGoogleAPIClient.class.getSimpleName() + ">" + StopGoogleApiClientTask.class.getSimpleName();

		@Override
		public String getLogTag() {
			return TAG;
		}

		private WeakReference<MTActivityWithGoogleAPIClient> activityWR;

		public StopGoogleApiClientTask(MTActivityWithGoogleAPIClient activity) {
			this.activityWR = new WeakReference<MTActivityWithGoogleAPIClient>(activity);
		}

		@Override
		protected Void doInBackgroundMT(Void... params) {
			MTActivityWithGoogleAPIClient activity = this.activityWR == null ? null : this.activityWR.get();
			if (activity == null) {
				return null;
			}
			activity.onBeforeClientDisconnected();
			GoogleApiClient googleApiClient = activity.getGoogleApiClientOrNull();
			if (googleApiClient != null) {
				googleApiClient.disconnect();
			}
			return null;
		}
	}

	public abstract void onBeforeClientDisconnected();

	@Override
	protected void onDestroy() {
		super.onDestroy();
		if (this.googleApiClient != null) {
			this.googleApiClient.unregisterConnectionCallbacks(this);
			this.googleApiClient.unregisterConnectionFailedListener(this);
			this.googleApiClient = null;
		}
	}

	@Override
	public void onConnected(Bundle connectionHint) {
		onClientConnected();
	}

	public abstract void onClientConnected();

	@Override
	public void onConnectionSuspended(int cause) {
	}

	@Override
	public void onConnectionFailed(ConnectionResult result) {
		if (this.resolvingError) {
			return;
		}
		if (result.hasResolution()) {
			try {
				this.resolvingError = true;
				result.startResolutionForResult(this, REQUEST_RESOLVE_ERROR);
			} catch (SendIntentException sie) {
				MTLog.w(this, sie, "Error while resolving Google Play Services error!");
				GoogleApiClient googleApiClient = getGoogleApiClientOrInit();
				if (googleApiClient != null) {
					googleApiClient.connect();
				}
			}
		} else {
			showErrorDialog(result.getErrorCode());
			this.resolvingError = true;
		}
	}

	private void showErrorDialog(int errorCode) {
		MainActivity.showNewDialog(getSupportFragmentManager(), ErrorDialogFragment.newInstance(errorCode));
	}

	private void onDialogDismissed() {
		this.resolvingError = false;
	}

	public static class ErrorDialogFragment extends MTDialogFragmentV4 {

		private static final String TAG = ErrorDialogFragment.class.getSimpleName();

		@Override
		public String getLogTag() {
			return TAG;
		}

		public static ErrorDialogFragment newInstance(int errorCode) {
			ErrorDialogFragment dialogFragment = new ErrorDialogFragment();
			Bundle args = new Bundle();
			args.putInt(DIALOG_ERROR, errorCode);
			dialogFragment.setArguments(args);
			return dialogFragment;
		}

		public ErrorDialogFragment() {
		}

		@Override
		public Dialog onCreateDialog(Bundle savedInstanceState) {
			int errorCode = getArguments().getInt(DIALOG_ERROR);
			return GoogleApiAvailability.getInstance().getErrorDialog(getActivity(), errorCode, REQUEST_RESOLVE_ERROR);
		}

		@Override
		public void onDismiss(DialogInterface dialog) {
			FragmentActivity activity = getActivity();
			if (activity != null && activity instanceof MTActivityWithGoogleAPIClient) {
				((MTActivityWithGoogleAPIClient) activity).onDialogDismissed();
			}
		}
	}
}

@@ -769,17 +769,8 @@
  MTA
-ppCompatA
 ctiv

Use custom get[Child]Fragments() to replace @hide @RestrictTo(LIBRARY_GROUP) SDK method.