// Path: app/src/main/java/com/chrynan/android_guitar_tuner/tuner/PitchPlayer.java
// public interface PitchPlayer {
// 
//     /**
//      * Starts playing the provided frequency and returns a {@link Completable} that performs the
//      * playing of the frequency.
//      *
//      * @param frequency The frequency to be played.
//      * @return A {@link Completable} running the playing operation until unsubscribed.
//      */
//     Completable startPlaying(double frequency);
// }
// 
// Path: app/src/main/java/com/chrynan/android_guitar_tuner/tuner/volume/VolumeObserver.java
// public interface VolumeObserver {
// 
//     /**
//      * Subscribes to the volume observer for volume states, either on an interval or changes to the
//      * devices volume state.
//      *
//      * @return An {@link Observable<VolumeState>} providing the volume states as long as subscribed.
//      */
//     Observable<VolumeState> startListening();
// }
// 
// Path: app/src/main/java/com/chrynan/android_guitar_tuner/tuner/volume/VolumeState.java
// public enum VolumeState {
// 
//     MUTED,
//     UNMUTED;
// 
//     /**
//      * Retrieves a {@link VolumeState} for the provided volume.
//      *
//      * @param volume The volume.
//      * @return A {@link VolumeState} representing the provided volume.
//      */
//     public static VolumeState forVolume(final int volume) {
//         if (volume < 1) {
//             return MUTED;
//         }
// 
//         return UNMUTED;
//     }
// }
// 
// Path: app/src/main/java/com/chrynan/android_guitar_tuner/ui/view/PitchView.java
// public interface PitchView {
// 
//     void onUpdateVolumeState(@StringRes int volumeStateText, @ColorRes int textColor);
// 
//     void onErrorPlayingNote(@StringRes int errorDescription, boolean showAction, @StringRes int errorAction, @ColorRes int actionColor);
// }


import com.chrynan.android_guitar_tuner.R;
import com.chrynan.android_guitar_tuner.tuner.PitchPlayer;
import com.chrynan.android_guitar_tuner.tuner.volume.VolumeObserver;
import com.chrynan.android_guitar_tuner.tuner.volume.VolumeState;
import com.chrynan.android_guitar_tuner.ui.view.PitchView;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import timber.log.Timber;

                    boolean showAction = retryCount < RETRY_COUNT_MAX;
                    int description = showAction ? R.string.pitch_player_error_playing_note_description_with_action
                            : R.string.pitch_player_error_playing_note_description_without_action;

                    view.onErrorPlayingNote(
                            description,
                            showAction,
                            R.string.pitch_player_error_playing_note_action,
                            R.color.snack_bar_action_color
                    );
                });
    }

    public void retryPlayingNote(final double noteFrequency) {
        retryCount++;
        startPlayingNote(noteFrequency);
    }

    public void stopPlayingNote() {
        if (pitchPlayerDisposable != null) {
            pitchPlayerDisposable.dispose();
        }
    }

    public void startListeningToVolumeChanges() {
        volumeDisposable = volumeObserver.startListening()
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe(state -> {
// Path: app/src/main/java/com/chrynan/android_guitar_tuner/tuner/PitchPlayer.java
// public interface PitchPlayer {
// 
//     /**
//      * Starts playing the provided frequency and returns a {@link Completable} that performs the
//      * playing of the frequency.
//      *
//      * @param frequency The frequency to be played.
//      * @return A {@link Completable} running the playing operation until unsubscribed.
//      */
//     Completable startPlaying(double frequency);
// }
// 
// Path: app/src/main/java/com/chrynan/android_guitar_tuner/tuner/volume/VolumeObserver.java
// public interface VolumeObserver {
// 
//     /**
//      * Subscribes to the volume observer for volume states, either on an interval or changes to the
//      * devices volume state.
//      *
//      * @return An {@link Observable<VolumeState>} providing the volume states as long as subscribed.
//      */
//     Observable<VolumeState> startListening();
// }
// 
// Path: app/src/main/java/com/chrynan/android_guitar_tuner/tuner/volume/VolumeState.java
// public enum VolumeState {
// 
//     MUTED,
//     UNMUTED;
// 
//     /**
//      * Retrieves a {@link VolumeState} for the provided volume.
//      *
//      * @param volume The volume.
//      * @return A {@link VolumeState} representing the provided volume.
//      */
//     public static VolumeState forVolume(final int volume) {
//         if (volume < 1) {
//             return MUTED;
//         }
// 
//         return UNMUTED;
//     }
// }
// 
// Path: app/src/main/java/com/chrynan/android_guitar_tuner/ui/view/PitchView.java
// public interface PitchView {
// 
//     void onUpdateVolumeState(@StringRes int volumeStateText, @ColorRes int textColor);
// 
//     void onErrorPlayingNote(@StringRes int errorDescription, boolean showAction, @StringRes int errorAction, @ColorRes int actionColor);
// }


// Path: app/src/main/java/com/chrynan/android_guitar_tuner/presenter/PitchPresenter.java
import com.chrynan.android_guitar_tuner.R;
import com.chrynan.android_guitar_tuner.tuner.PitchPlayer;
import com.chrynan.android_guitar_tuner.tuner.volume.VolumeObserver;
import com.chrynan.android_guitar_tuner.tuner.volume.VolumeState;
import com.chrynan.android_guitar_tuner.ui.view.PitchView;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import timber.log.Timber;


                    boolean showAction = retryCount < RETRY_COUNT_MAX;
                    int description = showAction ? R.string.pitch_player_error_playing_note_description_with_action
                            : R.string.pitch_player_error_playing_note_description_without_action;

                    view.onErrorPlayingNote(
                            description,
                            showAction,
                            R.string.pitch_player_error_playing_note_action,
                            R.color.snack_bar_action_color
                    );
                });
    }

    public void retryPlayingNote(final double noteFrequency) {
        retryCount++;
        startPlayingNote(noteFrequency);
    }

    public void stopPlayingNote() {
        if (pitchPlayerDisposable != null) {
            pitchPlayerDisposable.dispose();
        }
    }

    public void startListeningToVolumeChanges() {
        volumeDisposable = volumeObserver.startListening()
                .observeOn(AndroidSchedulers.mainThread())
                .subscribeOn(Schedulers.io())
                .subscribe(state -> {
                    if (state == VolumeState.MUTED) {