// Path: lib/src/main/java/com/github/niqdev/openwebnet/OpenSession.java
// public class OpenSession {
// 
//     private final OpenMessage request;
//     private final List<OpenMessage> response = new ArrayList<>();
// 
//     private OpenSession(OpenMessage request) {
//         checkNotNull(request, "request can't be null");
//         this.request = request;
//     }
// 
//     /**
//      * Helper method to create a new session.
//      *
//      * @param request message
//      * @return session
//      */
//     public static OpenSession newSession(OpenMessage request) {
//         return new OpenSession(request);
//     }
// 
//     /**
//      * Update the response messages.
//      *
//      * @param response messages
//      * @return session
//      */
//     public OpenSession addAllResponse(List<OpenMessage> response) {
//         checkNotNull(response, "response can't be null");
//         this.response.addAll(response);
//         return this;
//     }
// 
//     /**
//      * Update the response messages.
//      *
//      * @param response messages
//      * @return session
//      */
//     public OpenSession addResponse(OpenMessage response) {
//         checkNotNull(response, "response can't be null");
//         this.response.add(response);
//         return this;
//     }
// 
//     /**
//      * Returns the initial request message.
//      *
//      * @return request
//      */
//     public OpenMessage getRequest() {
//         return request;
//     }
// 
//     /**
//      * Returns the response messages.
//      *
//      * @return response
//      */
//     public List<OpenMessage> getResponse() {
//         return response;
//     }
// 
//     @Override
//     public String toString() {
//         return MoreObjects.toStringHelper(this)
//             .add("request", request.getValue())
//             .add("response", response)
//             .toString();
//     }
// }


import com.github.niqdev.openwebnet.OpenSession;
import com.google.common.collect.FluentIterable;
import rx.functions.Action0;
import rx.functions.Func1;
import java.util.List;
import static com.github.niqdev.openwebnet.message.Who.SOUND_SYSTEM_1;
import static com.github.niqdev.openwebnet.message.Who.SOUND_SYSTEM_2;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.lang.String.format;
     * @return message
     */
    public static SoundSystem requestTurnOff(String where, Type type, Source source) {
        return buildRequest(where, type, source, OFF_SOURCE_BASE_BAND, OFF_SOURCE_STEREO_CHANNEL);
    }

    private static SoundSystem buildRequest(String where, Type type, Source source, int baseBandValue, int stereoValue) {
        checkArgument(Type.isValid(type, where), "invalid where|type");
        switch (source) {
            case BASE_BAND:
                return new SoundSystem(format(FORMAT_REQUEST, WHO_16, baseBandValue, buildWhereValue(where, type)));
            case STEREO_CHANNEL:
                return new SoundSystem(format(FORMAT_REQUEST, WHO_16, stereoValue, buildWhereValue(where, type)));
        }
        throw new IllegalArgumentException("invalid source");
    }

    /**
     * Handle response from:
     * - {@link SoundSystem#requestTurnOn(String, Type, Source)}
     * - {@link SoundSystem#requestTurnOff(String, Type, Source)}
     * - {@link SoundSystem#requestVolumeUp(String, Type)}
     * - {@link SoundSystem#requestVolumeDown(String, Type)}
     * - {@link SoundSystem#requestStationUp(String, Type)}
     * - {@link SoundSystem#requestStationDown(String, Type)}
     *
     * @param onSuccess invoked if the request has been successfully received
     * @param onFail    invoked otherwise
     * @return {@code Observable<OpenSession>}
     */
// Path: lib/src/main/java/com/github/niqdev/openwebnet/OpenSession.java
// public class OpenSession {
// 
//     private final OpenMessage request;
//     private final List<OpenMessage> response = new ArrayList<>();
// 
//     private OpenSession(OpenMessage request) {
//         checkNotNull(request, "request can't be null");
//         this.request = request;
//     }
// 
//     /**
//      * Helper method to create a new session.
//      *
//      * @param request message
//      * @return session
//      */
//     public static OpenSession newSession(OpenMessage request) {
//         return new OpenSession(request);
//     }
// 
//     /**
//      * Update the response messages.
//      *
//      * @param response messages
//      * @return session
//      */
//     public OpenSession addAllResponse(List<OpenMessage> response) {
//         checkNotNull(response, "response can't be null");
//         this.response.addAll(response);
//         return this;
//     }
// 
//     /**
//      * Update the response messages.
//      *
//      * @param response messages
//      * @return session
//      */
//     public OpenSession addResponse(OpenMessage response) {
//         checkNotNull(response, "response can't be null");
//         this.response.add(response);
//         return this;
//     }
// 
//     /**
//      * Returns the initial request message.
//      *
//      * @return request
//      */
//     public OpenMessage getRequest() {
//         return request;
//     }
// 
//     /**
//      * Returns the response messages.
//      *
//      * @return response
//      */
//     public List<OpenMessage> getResponse() {
//         return response;
//     }
// 
//     @Override
//     public String toString() {
//         return MoreObjects.toStringHelper(this)
//             .add("request", request.getValue())
//             .add("response", response)
//             .toString();
//     }
// }


// Path: lib/src/main/java/com/github/niqdev/openwebnet/message/SoundSystem.java
import com.github.niqdev.openwebnet.OpenSession;
import com.google.common.collect.FluentIterable;
import rx.functions.Action0;
import rx.functions.Func1;
import java.util.List;
import static com.github.niqdev.openwebnet.message.Who.SOUND_SYSTEM_1;
import static com.github.niqdev.openwebnet.message.Who.SOUND_SYSTEM_2;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static java.lang.String.format;

     * @return message
     */
    public static SoundSystem requestTurnOff(String where, Type type, Source source) {
        return buildRequest(where, type, source, OFF_SOURCE_BASE_BAND, OFF_SOURCE_STEREO_CHANNEL);
    }

    private static SoundSystem buildRequest(String where, Type type, Source source, int baseBandValue, int stereoValue) {
        checkArgument(Type.isValid(type, where), "invalid where|type");
        switch (source) {
            case BASE_BAND:
                return new SoundSystem(format(FORMAT_REQUEST, WHO_16, baseBandValue, buildWhereValue(where, type)));
            case STEREO_CHANNEL:
                return new SoundSystem(format(FORMAT_REQUEST, WHO_16, stereoValue, buildWhereValue(where, type)));
        }
        throw new IllegalArgumentException("invalid source");
    }

    /**
     * Handle response from:
     * - {@link SoundSystem#requestTurnOn(String, Type, Source)}
     * - {@link SoundSystem#requestTurnOff(String, Type, Source)}
     * - {@link SoundSystem#requestVolumeUp(String, Type)}
     * - {@link SoundSystem#requestVolumeDown(String, Type)}
     * - {@link SoundSystem#requestStationUp(String, Type)}
     * - {@link SoundSystem#requestStationDown(String, Type)}
     *
     * @param onSuccess invoked if the request has been successfully received
     * @param onFail    invoked otherwise
     * @return {@code Observable<OpenSession>}
     */
    public static Func1<OpenSession, OpenSession> handleResponse(Action0 onSuccess, Action0 onFail) {