package com.musicocracy.fpgk.domain.spotify;

import com.musicocracy.fpgk.domain.dj.DjAlgorithm;
import com.musicocracy.fpgk.domain.net.SharedSubject;
import com.musicocracy.fpgk.domain.util.Logger;
import com.spotify.sdk.android.player.Error;
import com.spotify.sdk.android.player.Metadata;
import com.spotify.sdk.android.player.PlayerEvent;
import com.spotify.sdk.android.player.SpotifyPlayer;

import java.sql.SQLException;
import java.util.concurrent.TimeUnit;
import rx.Observable;
import rx.functions.Action1;

public class SpotifyPlayerHandler implements SpotifyPlayer.NotificationCallback {
    private static final String TAG = "SpotifyPlayerHandler";
    private static final int TIME_BEFORE_NEXT_SONG = 10000; //ms
    private final Logger log;
    private final DjAlgorithm djAlgorithm;
    private SpotifyPlayer player;
    private boolean playerStarted = false;
    private final SharedSubject<Metadata.Track> newTrackPlayingSubject = SharedSubject.create();

    public SpotifyPlayerHandler(Logger log, SpotifyPlayer player, DjAlgorithm djAlgorithm) {
        this.log = log;
        this.player = player;
        this.djAlgorithm = djAlgorithm;

        player.addNotificationCallback(this);
    }

    public void play() {
        if (!playerStarted) {
            try {
                player.playUri(null, djAlgorithm.dequeueNextSongUri(), 0, 0);
            } catch (SQLException e) {
                log.error(TAG, e.toString());
            }
            playerStarted = true;
        }
    }

    @Override
    public void onPlaybackEvent(PlayerEvent playerEvent) {
        if (playerEvent == PlayerEvent.kSpPlaybackNotifyTrackChanged) {
            newTrackPlayingSubject.onNext(player.getMetadata().currentTrack);
            scheduleTimer();
        }
    }

    @Override
    public void onPlaybackError(Error error) {
        log.error(TAG, "Error in Playback of Spotify Player.");
    }

    private void scheduleTimer() {
        long timerDelay = player.getMetadata().currentTrack.durationMs - TIME_BEFORE_NEXT_SONG;

        // If timer delay is negative, start the timer now
        if (timerDelay < 0) {
            timerDelay = 0;
        }

        Observable.timer(timerDelay , TimeUnit.MILLISECONDS)
            .subscribe(new Action1<Long>() {
                @Override
                public void call(Long aLong) {
                    String nextURI = null;
                    try {
                        nextURI = djAlgorithm.dequeueNextSongUri();
                    } catch (SQLException e) {
                        log.error(TAG, e.toString());
                    }
                    if (nextURI != null) {
                        player.queue(null, nextURI);
                        log.info(TAG, "Song Queued(URI): " + nextURI);
                    } else {
                        log.error(TAG, "Next song from DJ algorithm is null.");
                        scheduleTimer();
                    }
                }
            });
    }

    public Observable<Metadata.Track> newSongPlaying() {
        return newTrackPlayingSubject.asObservable();
    }

    public Metadata.Track getCurrentlyPlayingTrack() {
        return newTrackPlayingSubject.getLast();
    }

    public void onDestroy() {
        newTrackPlayingSubject.onCompleted();
        player.removeNotificationCallback(this);
        playerStarted = false;
    }
}

@@ -719,16 +719,73 @@
 0; //ms%0A
+    private static final int DEFAULT_WAIT = 10000; // ms%0A
     priv
@@ -802,24 +802,24 @@
 Logger log;%0A
-
     private 
@@ -2027,16 +2027,107 @@
 rDelay =
+ DEFAULT_WAIT;%0A        if (player.getPlaybackState().isPlaying) %7B%0A             timerDelay =
  player.
@@ -2188,16 +2188,26 @@
 XT_SONG;
+%0A        %7D
 %0A%0A      
@@ -2806,16 +2806,39 @@
  != null
+ && !nextURI.equals(%22%22)
 ) %7B%0A    
@@ -2861,36 +2861,317 @@
     
-player.queue(null, nextURI);
+if (player.getPlaybackState().isPlaying) %7B%0A                            player.queue(null, nextURI);%0A                        %7D else %7B%0A                            // If player is not currently playing something, play now%0A                            player.playUri(null, nextURI, 0, 0);%0A                        %7D
 %0A   
@@ -3259,32 +3259,32 @@
        %7D else %7B%0A
-
                 
@@ -3342,16 +3342,25 @@
  is null
+ or empty
 .%22);%0A   

Set playerHandler to check for new tracks every 10 seconds if it has nothing to play.