// Path: common/src/main/java/com/github/jbarr21/goproremote/common/data/Constants.java
// public class Constants {
// 
//     public static final String SCHEME_WEAR = "wear";
// 
//     // Message and Data paths
//     public static final String COMMAND_REQUEST_PATH = "/command/request";
//     public static final String COMMAND_RESPONSE_PATH = "/command/response";
//     public static final String CONFIG_PATH = "/config";
// 
//     // Shared timeout values
//     public static final int WEARABLE_CONN_TIMEOUT_MILLIS = 500;
//     public static final int GO_PRO_COMMAND_TIMEOUT_SEC = 5;
// 
//     public static final int TAKE_PHOTO = 10;
//     public static final int START_VIDEO = 20;
//     public static final int STOP_VIDEO = 21;
//     public static final int SWITCH_TO_PHOTO = 1;
//     public static final int SWITCH_TO_VIDEO = 2;
//     public static final int POWER_ON = 30;
//     public static final int POWER_OFF = 31;
// }
// 
// Path: common/src/main/java/com/github/jbarr21/goproremote/common/data/GoProCommandRequest.java
// @AutoValue
// public abstract class GoProCommandRequest {
//     public abstract GoProCommand command();
//     public abstract long timestamp();
// 
//     public static GoProCommandRequest create(GoProCommand command, long timestamp) {
//         return new AutoValue_GoProCommandRequest(command, timestamp);
//     }
// 
//     public static JsonAdapter<GoProCommandRequest> jsonAdapter(Moshi moshi) {
//         return new AutoValue_GoProCommandRequest.MoshiJsonAdapter(moshi);
//     }
// 
//     public long id() {
//         return command() != null ? command().getId() : GoProCommand.UNKNOWN.getId();
//     }
// 
// }
// 
// Path: common/src/main/java/com/github/jbarr21/goproremote/common/data/GoProCommandResponse.java
// @AutoValue
// public abstract class GoProCommandResponse {
//     public abstract long requestId();
//     public abstract boolean success();
//     @Nullable public abstract String message();
// 
//     public static GoProCommandResponse create(long requestId, boolean success, String message) {
//         return new AutoValue_GoProCommandResponse(requestId, success, message);
//     }
// 
//     public static JsonAdapter<GoProCommandResponse> jsonAdapter(Moshi moshi) {
//         return new AutoValue_GoProCommandResponse.MoshiJsonAdapter(moshi);
//     }
// }
// 
// Path: common/src/main/java/com/github/jbarr21/goproremote/common/data/Constants.java
// public static final int GO_PRO_COMMAND_TIMEOUT_SEC = 5;
// 
// Path: common/src/main/java/com/github/jbarr21/goproremote/common/data/Constants.java
// public static final int WEARABLE_CONN_TIMEOUT_MILLIS = 500;


import android.os.Looper;
import android.support.annotation.NonNull;
import com.github.jbarr21.goproremote.common.data.Constants;
import com.github.jbarr21.goproremote.common.data.GoProCommandRequest;
import com.github.jbarr21.goproremote.common.data.GoProCommandResponse;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.wearable.MessageApi;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.Wearable;
import com.squareup.moshi.Moshi;
import com.twotoasters.servos.util.ListUtils;
import java.net.ConnectException;
import java.util.List;
import java.util.concurrent.TimeUnit;
import rx.Observable;
import rx.functions.Func0;
import rx.functions.Func1;
import rx.schedulers.Schedulers;
import timber.log.Timber;
import static com.github.jbarr21.goproremote.common.data.Constants.GO_PRO_COMMAND_TIMEOUT_SEC;
import static com.github.jbarr21.goproremote.common.data.Constants.WEARABLE_CONN_TIMEOUT_MILLIS;
                    @Override
                    public Observable<String> call(ConnectionResult connectionResult) {
                        return fetchPeerId(googleApiClient);
                    }
                })
                .flatMap(new Func1<String, Observable<Integer>>() {
                    @Override
                    public Observable<Integer> call(String peerId) {
                        return sendCommandRequest(googleApiClient, peerId, commandRequest);
                    }
                })
                .subscribeOn(Schedulers.newThread());
    }

    private static Observable<ConnectionResult> connectGoogleApiClient(final GoogleApiClient googleApiClient) {
        return Observable.defer(new Func0<Observable<ConnectionResult>>() {
            @Override
            public Observable<ConnectionResult> call() {
                ConnectionResult connectionResult = googleApiClient.blockingConnect(WEARABLE_CONN_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
                if (connectionResult != null && connectionResult.isSuccess()) {
                    return Observable.just(connectionResult);
                } else {
                    return Observable.error(new ConnectException(connectionResult != null ? connectionResult.toString() : "Failed to connect to Google API client"));
                }
            }
        });
    }

    private static Observable<String> fetchPeerId(GoogleApiClient googleApiClient) {
        Timber.d("fetchPeerId - isOnMainThread? %b", Looper.myLooper() == Looper.getMainLooper());
// Path: common/src/main/java/com/github/jbarr21/goproremote/common/data/Constants.java
// public class Constants {
// 
//     public static final String SCHEME_WEAR = "wear";
// 
//     // Message and Data paths
//     public static final String COMMAND_REQUEST_PATH = "/command/request";
//     public static final String COMMAND_RESPONSE_PATH = "/command/response";
//     public static final String CONFIG_PATH = "/config";
// 
//     // Shared timeout values
//     public static final int WEARABLE_CONN_TIMEOUT_MILLIS = 500;
//     public static final int GO_PRO_COMMAND_TIMEOUT_SEC = 5;
// 
//     public static final int TAKE_PHOTO = 10;
//     public static final int START_VIDEO = 20;
//     public static final int STOP_VIDEO = 21;
//     public static final int SWITCH_TO_PHOTO = 1;
//     public static final int SWITCH_TO_VIDEO = 2;
//     public static final int POWER_ON = 30;
//     public static final int POWER_OFF = 31;
// }
// 
// Path: common/src/main/java/com/github/jbarr21/goproremote/common/data/GoProCommandRequest.java
// @AutoValue
// public abstract class GoProCommandRequest {
//     public abstract GoProCommand command();
//     public abstract long timestamp();
// 
//     public static GoProCommandRequest create(GoProCommand command, long timestamp) {
//         return new AutoValue_GoProCommandRequest(command, timestamp);
//     }
// 
//     public static JsonAdapter<GoProCommandRequest> jsonAdapter(Moshi moshi) {
//         return new AutoValue_GoProCommandRequest.MoshiJsonAdapter(moshi);
//     }
// 
//     public long id() {
//         return command() != null ? command().getId() : GoProCommand.UNKNOWN.getId();
//     }
// 
// }
// 
// Path: common/src/main/java/com/github/jbarr21/goproremote/common/data/GoProCommandResponse.java
// @AutoValue
// public abstract class GoProCommandResponse {
//     public abstract long requestId();
//     public abstract boolean success();
//     @Nullable public abstract String message();
// 
//     public static GoProCommandResponse create(long requestId, boolean success, String message) {
//         return new AutoValue_GoProCommandResponse(requestId, success, message);
//     }
// 
//     public static JsonAdapter<GoProCommandResponse> jsonAdapter(Moshi moshi) {
//         return new AutoValue_GoProCommandResponse.MoshiJsonAdapter(moshi);
//     }
// }
// 
// Path: common/src/main/java/com/github/jbarr21/goproremote/common/data/Constants.java
// public static final int GO_PRO_COMMAND_TIMEOUT_SEC = 5;
// 
// Path: common/src/main/java/com/github/jbarr21/goproremote/common/data/Constants.java
// public static final int WEARABLE_CONN_TIMEOUT_MILLIS = 500;


// Path: common/src/main/java/com/github/jbarr21/goproremote/common/utils/MessageUtils.java
import android.os.Looper;
import android.support.annotation.NonNull;
import com.github.jbarr21.goproremote.common.data.Constants;
import com.github.jbarr21.goproremote.common.data.GoProCommandRequest;
import com.github.jbarr21.goproremote.common.data.GoProCommandResponse;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.wearable.MessageApi;
import com.google.android.gms.wearable.Node;
import com.google.android.gms.wearable.Wearable;
import com.squareup.moshi.Moshi;
import com.twotoasters.servos.util.ListUtils;
import java.net.ConnectException;
import java.util.List;
import java.util.concurrent.TimeUnit;
import rx.Observable;
import rx.functions.Func0;
import rx.functions.Func1;
import rx.schedulers.Schedulers;
import timber.log.Timber;
import static com.github.jbarr21.goproremote.common.data.Constants.GO_PRO_COMMAND_TIMEOUT_SEC;
import static com.github.jbarr21.goproremote.common.data.Constants.WEARABLE_CONN_TIMEOUT_MILLIS;

                    @Override
                    public Observable<String> call(ConnectionResult connectionResult) {
                        return fetchPeerId(googleApiClient);
                    }
                })
                .flatMap(new Func1<String, Observable<Integer>>() {
                    @Override
                    public Observable<Integer> call(String peerId) {
                        return sendCommandRequest(googleApiClient, peerId, commandRequest);
                    }
                })
                .subscribeOn(Schedulers.newThread());
    }

    private static Observable<ConnectionResult> connectGoogleApiClient(final GoogleApiClient googleApiClient) {
        return Observable.defer(new Func0<Observable<ConnectionResult>>() {
            @Override
            public Observable<ConnectionResult> call() {
                ConnectionResult connectionResult = googleApiClient.blockingConnect(WEARABLE_CONN_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
                if (connectionResult != null && connectionResult.isSuccess()) {
                    return Observable.just(connectionResult);
                } else {
                    return Observable.error(new ConnectException(connectionResult != null ? connectionResult.toString() : "Failed to connect to Google API client"));
                }
            }
        });
    }

    private static Observable<String> fetchPeerId(GoogleApiClient googleApiClient) {
        Timber.d("fetchPeerId - isOnMainThread? %b", Looper.myLooper() == Looper.getMainLooper());
        List<Node> nodes = Wearable.NodeApi.getConnectedNodes(googleApiClient).await(WEARABLE_CONN_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS).getNodes();