public class SongDTO implements Parcelable {

    private String songTitle;
    private long songDuration;
    private String songLocation;
    private String albumId;
    private String id;

    public void setSongTitle(String songTitle) {
        this.songTitle = songTitle;
    }

    public String getSongTitle() {
        return songTitle;
    }

    public void setSongDuration(long songDuration) {
        this.songDuration = songDuration;
    }

    public long getSongDuration() {
        return songDuration;
    }

    public void setSongLocation(String songLocation) {
        this.songLocation = songLocation;
    }

    public String getSongLocation() {
        return songLocation;
    }

    public String getAlbumId() {
        return albumId;
    }

    public void setAlbumId(String albumId) {
        this.albumId = albumId;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getId() {
        return id;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.songTitle);
        dest.writeLong(this.songDuration);
        dest.writeString(this.songLocation);
        dest.writeString(this.albumId);
        dest.writeString(this.id);
    }

    public SongDTO() {
    }

    protected SongDTO(Parcel in) {
        this.songTitle = in.readString();
        this.songDuration = in.readLong();
        this.songLocation = in.readString();
        this.albumId = in.readString();
        this.id = in.readString();
    }

    public static final Parcelable.Creator<SongDTO> CREATOR = new Parcelable.Creator<SongDTO>() {
        public SongDTO createFromParcel(Parcel source) {
            return new SongDTO(source);
        }

        public SongDTO[] newArray(int size) {
            return new SongDTO[size];
        }
    };
} public class SongFragment extends Fragment implements MediaPlayer.OnErrorListener,
        MediaPlayer.OnInfoListener, MediaPlayer.OnPreparedListener {
    private static final String SONG_PARAM = "song";
    private static final String SONG_POSITION_PARAM = "songPosition";

    private SongFragmentCallback callback;
    private SongDTO song;
    private RhythmSong rhythmSong;
    private int songPosition;
    private MediaPlayer mediaPlayer;

    private TextView track;
    private CircularSeekBar trackProgress;
    private CircleImageView albumCover;
    private TextView txtDuration;
    private ImageView playButton;
    private int vibrantColor;
    private int backgroundColor;
    private static Handler handler;

    private boolean beenDrawn = false;


    public static SongFragment newInstance(SongDTO song, int position) {
        SongFragment fragment = new SongFragment();
        Bundle args = new Bundle();
        args.putParcelable(SONG_PARAM, song);
        args.putInt(SONG_POSITION_PARAM, position);
        fragment.setArguments(args);
        return fragment;
    }

    public SongFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (getArguments().size() > 0) {
            song = getArguments().getParcelable(SONG_PARAM);
            songPosition = getArguments().getInt(SONG_POSITION_PARAM);
            rhythmSong = MusicDataUtility.getSongMeta(song.getSongLocation());
        }
        handler = new Handler();
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View rootView = inflater.inflate(R.layout.fragment_song, container, false);
        beenDrawn = true;
        track = (TextView) rootView.findViewById(R.id.txt_track);
        txtDuration = (TextView) rootView.findViewById(R.id.txt_duration);
        playButton = (ImageView) rootView.findViewById(R.id.play_button);

        trackProgress = (CircularSeekBar) rootView.findViewById(R.id.track_progress);
        trackProgress.setMax(100);

        trackProgress.setOnSeekBarChangeListener(new CircularSeekBar.OnCircularSeekBarChangeListener() {
            @Override
            public void onProgressChanged(CircularSeekBar circularSeekBar, int progress, boolean fromUser) {
                if (mediaPlayer != null) {
                    float currentDuration = (((float) circularSeekBar.getProgress() / 100) * mediaPlayer.getDuration());
                    updateDuration(milliSecondsToTimer((long) currentDuration), TimeFormatUtils.secondsToTimer(mediaPlayer.getDuration() / 1000));
                }
            }

            @Override
            public void onStopTrackingTouch(CircularSeekBar seekBar) {
                if (mediaPlayer.isPlaying()) {
                    mediaPlayer.pause();
                }
                mediaPlayer.start();
                startTimer();
                int currentMill = (int) (((float) seekBar.getProgress() / 100) * mediaPlayer.getDuration());
                mediaPlayer.seekTo(currentMill);
                playButton.setImageResource(R.drawable.ic_pause_white_24dp);
            }

            @Override
            public void onStartTrackingTouch(CircularSeekBar seekBar) {
                stopTimer();
            }
        });

        albumCover = (CircleImageView) rootView.findViewById(R.id.album_cover);

        playButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mediaPlayer.isPlaying()) {
                    playButton.setImageResource(R.drawable.ic_play_arrow_white_24dp);
                    mediaPlayer.pause();
                    stopTimer();
                    playerNotification(Constants.ACTION_PAUSE);
                } else {
                    playButton.setImageResource(R.drawable.ic_pause_white_24dp);
                    CustomAnimUtil.overShootAnimation(albumCover);
                    mediaPlayer.start();
                    startTimer();
                    playerNotification(Constants.ACTION_PLAY);
                }
            }
        });
        removePlayerListeners();
        setPlayerListeners();
        if (mediaPlayer != null && mediaPlayer.isPlaying() && rhythmSong.getSongLocation().equals(PlayBackUtil.getCurrentSong().getSongLocation())) {
            startTimer();
        }

        updatePlayerUI();
        return rootView;
    }

    @Override
    public void onPause() {
        super.onPause();
        stopTimer();
        handler.removeCallbacksAndMessages(null);
        removePlayerListeners();
    }

    @Override
    public void onAttach(Context context) {
        super.onAttach(context);
        callback = (SongFragmentCallback) context;
    }

    @Override
    public void onDetach() {
        super.onDetach();
        callback = null;
        handler.removeCallbacksAndMessages(null);
        removePlayerListeners();
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isVisibleToUser) {
            if (mediaPlayer == null) {
                if (callback.songChangedFromNotification()) {
                    mediaPlayer = PlayBackUtil.getMediaPlayer();
                    callback.resetChangedSongFromNotification();
                } else {
                    if (PlayBackUtil.getCurrentSong() != null && rhythmSong.getSongLocation()
                            .equals(PlayBackUtil.getCurrentSong().getSongLocation())) {
                        mediaPlayer = PlayBackUtil.getMediaPlayer();
                        startTimer();

                    } else {
                        PlayBackUtil.setCurrentSong(rhythmSong);
                        mediaPlayer = PlayBackUtil.setMediaPlayer(getContext()
                                .getApplicationContext(), rhythmSong.getSongLocation());
                    }
                }
                removePlayerListeners();
                setPlayerListeners();
            }

            if (beenDrawn) {
                trackProgress.setProgress(0);
                updateDuration("0:00", milliSecondsToTimer(mediaPlayer.getDuration()));
            }
            callback.setToolBarText(rhythmSong.getArtistTitle(), rhythmSong.getAlbumTitle());
            callback.changePlayerStyle(vibrantColor, backgroundColor, songPosition);
            PlayBackUtil.setCurrentSong(rhythmSong);
        } else {
            if (mediaPlayer != null) {
                stopTimer();
                removePlayerListeners();
                mediaPlayer.stop();
                mediaPlayer.release();
                mediaPlayer = null;
            }
        }
    }

    private void setPlayerListeners() {
        if (mediaPlayer != null) {
            mediaPlayer.setOnErrorListener(this);
            mediaPlayer.setOnInfoListener(this);
            mediaPlayer.setOnPreparedListener(this);
            mediaPlayer.setScreenOnWhilePlaying(false);
        }
    }

    private void removePlayerListeners() {
        if (mediaPlayer != null) {
            mediaPlayer.setOnErrorListener(null);
            mediaPlayer.setOnInfoListener(null);
            mediaPlayer.setOnPreparedListener(null);
            mediaPlayer.setScreenOnWhilePlaying(false);
            stopTimer();
        }
    }

    @Override
    public void onPrepared(final MediaPlayer mp) {
        updateDuration("0:00", milliSecondsToTimer(mp.getDuration()));
        startTimer();
        mp.start();
        playerNotification(Constants.ACTION_PLAY);
        updateSongCount();
    }

    private void updateSongCount() {
        MusicDataUtility.updateSongCount(song.getId(), getContext());
    }

    private void playerNotification(String action) {
        Intent intent = new Intent(getContext().getApplicationContext(), MediaPlayerService.class);
        intent.setAction(action);
        intent.putExtra(SONG_PARAM, rhythmSong);
        intent.putExtra(SONG_POSITION_PARAM, songPosition);
        getActivity().startService(intent);
    }

    @Override
    public boolean onInfo(MediaPlayer mp, int what, int extra) {
        return false;
    }

    @Override
    public boolean onError(MediaPlayer mp, int what, int extra) {
        removePlayerListeners();
        mediaPlayer = PlayBackUtil.setMediaPlayer(getContext().getApplicationContext(),
                rhythmSong.getSongLocation());
        setPlayerListeners();
        return false;
    }


    private void startTimer() {
        mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
                stopTimer();
                trackProgress.setProgress(0);
                updateDuration("0:00", milliSecondsToTimer(mediaPlayer.getDuration()));
                playButton.setImageResource(R.drawable.ic_play_arrow_white_24dp);
                mediaPlayer.pause();

                switch (PlayBackUtil.getCurrentPlayMode()) {
                    case SHUFFLE_REPEAT:
                    case ALL_REPEAT:
                        playNext();
                        break;
                    case NONE:
                        if (songPosition != PlayBackUtil.getCurrentSongPosition()) {
                            playNext();
                        }
                        break;
                    case SINGLE_REPEAT:
                        startTimer();
                        mediaPlayer.start();
                        break;
                }
            }
        });
        handler.postDelayed(mRunnable, 500);
    }

    private void playNext() {
        if (callback != null) {
            callback.playNext();
        } else {
            Intent intent = new Intent(getContext().getApplicationContext(), MediaPlayerService.class);
            intent.setAction(Constants.ACTION_NEXT);
            getContext().getApplicationContext().startService(intent);
        }
    }

    private void stopTimer() {
        if (handler != null) {
            handler.removeCallbacks(mRunnable);
        }
    }

    private Runnable mRunnable = new Runnable() {
        @Override
        public void run() {
            if (mediaPlayer != null && beenDrawn) {
                if (!mediaPlayer.isPlaying() || !trackProgress.isPressed()) {
                    final int currentProgress = (int) (((float) mediaPlayer.getCurrentPosition() / mediaPlayer.getDuration()) * 100);
                    if (getActivity() != null) {
                        getActivity().runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                trackProgress.setProgress(currentProgress);
                                if (mediaPlayer != null) {
                                    playButton.setImageResource(mediaPlayer.isPlaying()
                                            ? R.drawable.ic_pause_white_24dp : R.drawable.ic_play_arrow_white_24dp);
                                    updateDuration(milliSecondsToTimer(mediaPlayer.getCurrentPosition()),
                                            milliSecondsToTimer(mediaPlayer.getDuration()));
                                }
                            }
                        });
                    }
                }
            }
            handler.postDelayed(mRunnable, 500);
        }
    };

    private void updateDuration(String currentDuration, String totalDuration) {
        if (getActivity() != null) {
            txtDuration.setText(getActivity().getResources().getString(R.string.duration_format, currentDuration, totalDuration));
        }
    }

    private void updatePlayerUI() {
        updateDuration("0:00", milliSecondsToTimer(rhythmSong.getDuration()));
        track.setText(rhythmSong.getTrackTitle());
        if (rhythmSong.getImageData() != null) {
            final Bitmap bmp = BitmapUtils.decodeSampledBitmapFromResource(rhythmSong.getImageData(), 200, 200);
            albumCover.setImageBitmap(bmp);
            Palette.Swatch vibrantSwatch = new Palette.Builder(bmp).generate().getLightVibrantSwatch();
            if (vibrantSwatch != null) {
                vibrantColor = vibrantSwatch.getRgb();
                backgroundColor = vibrantSwatch.getBodyTextColor();
                changePlayerStyle(vibrantSwatch.getRgb());
                callback.changePlayerStyle(vibrantColor, backgroundColor, songPosition);
            } else {
                vibrantColor = getResources().getColor(R.color.color_primary);
                backgroundColor = getResources().getColor(R.color.color_primary_dark);
                callback.changePlayerStyle(vibrantColor, backgroundColor, songPosition);
            }
        }
    }

    private void changePlayerStyle(int vibrantColor) {
        track.setTextColor(vibrantColor);
        txtDuration.setTextColor(vibrantColor);
        trackProgress.setCircleProgressColor(vibrantColor);
        trackProgress.setPointerColor(vibrantColor);
        String alphaColor = Integer.toHexString(vibrantColor);
        if (alphaColor.length() > 6) {
            alphaColor = "#88" + alphaColor.substring(2);
        } else {
            alphaColor = "#88" + alphaColor;

        }
        trackProgress.setPointerAlphaOnTouch(Color.parseColor(alphaColor));
        trackProgress.setPointerHaloColor(Color.parseColor(alphaColor));
    }

    private String milliSecondsToTimer(long milliseconds) {
        String finalTimerString = "";
        String secondsString;

        // Convert total duration into time
        int hours = (int) (milliseconds / (1000 * 60 * 60));
        int minutes = (int) (milliseconds % (1000 * 60 * 60)) / (1000 * 60);
        int seconds = (int) ((milliseconds % (1000 * 60 * 60)) % (1000 * 60) / 1000);
        // Add hours if there
        if (hours > 0) {
            finalTimerString = hours + ":";
        }

        // Prepending 0 to seconds if it is one digit
        if (seconds < 10) {
            secondsString = "0" + seconds;
        } else {
            secondsString = "" + seconds;
        }

        finalTimerString = finalTimerString + minutes + ":" + secondsString;

        // return timer string
        return finalTimerString;
    }
} public interface SongFragmentCallback {
    void changePlayerStyle(int vibrantColor, int backgroundColor, int songPosition);

    void setToolBarText(String artistTitle, String albumTitle);

    void resetChangedSongFromNotification();

    boolean songChangedFromNotification();

    void playNext();
} public class Constants {

    public static final String ACTION_PLAY = "action_play";
    public static final String ACTION_PAUSE = "action_pause";
    public static final String ACTION_REWIND = "action_rewind";
    public static final String ACTION_FAST_FORWARD = "action_fast_foward";
    public static final String ACTION_NEXT = "action_next";
    public static final String ACTION_PREVIOUS = "action_previous";
    public static final String ACTION_STOP = "action_stop";
    public static final String LOG_TAG = "MediaService";
    public static final String PLAYER = "player";

} public class SendToDataLayerThread extends Thread {
    private String path;
    private DataMap dataMap;
    private GoogleApiClient googleClient;

    // Constructor for sending data objects to the data layer
    public SendToDataLayerThread(String p, DataMap data, GoogleApiClient googleClient) {
        this.path = p;
        this.dataMap = data;
        this.googleClient = googleClient;
    }

    public void run() {
        NodeApi.GetConnectedNodesResult nodes = Wearable.NodeApi.getConnectedNodes(googleClient).await();
        for (Node node : nodes.getNodes()) {

            // Construct a DataRequest and send over the data layer
            PutDataMapRequest putDMR = PutDataMapRequest.create(path);
            putDMR.getDataMap().putAll(dataMap);
            PutDataRequest request = putDMR.asPutDataRequest();
            DataApi.DataItemResult result = Wearable.DataApi.putDataItem(googleClient, request).await();
            if (result.getStatus().isSuccess()) {
                Log.v("myTag", "DataMap: " + dataMap + " sent to: " + node.getDisplayName());
            } else {
                // Log an error
                Log.v("myTag", "ERROR: failed to send DataMap");
            }
        }
    }
} public class MusicDataUtility {

    private static boolean isUpdating = false;

    // Constructor
    public MusicDataUtility() {
    }

    private static void getMusicContent(Context context) {
        getMusicContentByUri(context, MediaStore.Audio.Media.EXTERNAL_CONTENT_URI);
        getMusicContentByUri(context, MediaStore.Audio.Media.INTERNAL_CONTENT_URI);
    }

    private static void getMusicContentByUri(Context context, Uri contentUri) {
        ContentResolver cr = context.getContentResolver();

        String selection = MediaStore.Audio.Media.IS_MUSIC + "!= 0";
        String sortOrder = MediaStore.Audio.Media.TITLE + " ASC";
        Cursor cur = cr.query(contentUri, null, selection, null, sortOrder);
        int count;

        if (cur != null) {
            count = cur.getCount();

            if (count > 0) {
                while (cur.moveToNext()) {
                    String data = cur.getString(cur.getColumnIndex(MediaStore.Audio.Media.DATA));
                    createSongEntry(context, data);
                }
            }
            cur.close();
        }
    }

    public static byte[] getImageData(String songLocation) {
        File songFile = new File(songLocation);
        if (songFile.exists()) {
            return new MusicMetaData(songLocation).getAlbumArt();
        }
        return null;
    }

    public static RhythmSong getSongMeta(String songLocation) {
        MusicMetaData musicMetaData = new MusicMetaData(songLocation);
        String artist = musicMetaData.getArtistName() != null ? musicMetaData.getArtistName() : "Unknown Artist";
        String album = musicMetaData.getAlbumName() != null ? musicMetaData.getAlbumName() : "Unknown Album";
        String track = musicMetaData.getSongTitle() != null ? musicMetaData.getSongTitle() : "Unknown Track";
        byte[] imageData = musicMetaData.getAlbumArt();
        long duration = musicMetaData.getDuration() / 1000;
        return new RhythmSong.RhythmSongBuilder().songLocation(songLocation).artistTitle(artist).albumTitle(album)
                .trackTitle(track).imageData(imageData).duration(duration).build();
    }

    public static List<SearchResult> getAllSearchResults(Context context) {
        List<SearchResult> results = new ArrayList<>();
        List<Artist> artists = allArtists(context);
        for (Artist artist : artists) {
            results.add(createSearchResult(artist.getId(), artist.getArtistName(), artist.getAlbums().size() + " albums", SearchResult.ResultType.ARTIST));
            for (Album album : artist.getAlbums()) {
                results.add(createSearchResult(album.getId(), album.getAlbumTitle(), artist.getArtistName(), SearchResult.ResultType.ALBUM));
                for (Song song : album.getSongs()) {
                    results.add(createSearchResult(song.getId(), song.getSongTitle(),
                            artist.getArtistName() + " - " + album.getAlbumTitle()
                            , SearchResult.ResultType.SONG));
                }
            }
        }
        Collections.sort(results, new Comparator<SearchResult>() {
            @Override
            public int compare(SearchResult lhs, SearchResult rhs) {
                return lhs.getResultType().compareTo(rhs.getResultType());
            }
        });
        int lastIndexOfArtists = 0;
        int lastIndexOfAlbums = 0;
        SearchResult.ResultType resultType;
        for (int i = 0; i < results.size(); i++) {
            resultType = results.get(i).getResultType();
            if (resultType == SearchResult.ResultType.ARTIST) {
                lastIndexOfArtists = i;
            } else if (resultType == SearchResult.ResultType.ALBUM) {
                lastIndexOfAlbums = i;
            }
        }
        if (results.size() > 0) {
            results.add(0, createSearchResult(null, "Artists", null, SearchResult.ResultType.HEADER));
            results.add(lastIndexOfArtists + 2, createSearchResult(null, "Albums", null, SearchResult.ResultType.HEADER));
            results.add(lastIndexOfAlbums + 3, createSearchResult(null, "Songs", null, SearchResult.ResultType.HEADER));
            return results;
        } else {
            return null;
        }
    }

    private static SearchResult createSearchResult(String id, String mainTitle, String subTitle, SearchResult.ResultType resultType) {
        return new SearchResult.SearchResultBuilder().id(id).mainTitle(mainTitle).subTitle(subTitle).setResultType(resultType).build();
    }

    public static void updateMusicDB(Context context) {
        if (!isUpdating) {
            isUpdating = true;
            getMusicContent(context);
            isUpdating = false;
        }
    }

    private static void createSongEntry(Context context, String songPath) {
        RhythmSong songEntry = getSongMeta(songPath);

        Realm realm = Realm.getInstance(context);
        realm.beginTransaction();
        Artist artistRecord = getOrCreateArtist(realm, songEntry);
        Album albumRecord = getOrCreateAlbum(realm, artistRecord, songEntry);
        getOrCreateSong(realm, albumRecord, songEntry.getTrackTitle(), songEntry.getDuration(), songPath);
        realm.commitTransaction();
        realm.close();
    }

    private static Artist getOrCreateArtist(Realm realm, RhythmSong rhythmSong) {
        if (rhythmSong.getArtistTitle().equals("Untitled Artist")) {
            Artist query = realm.where(Artist.class)
                    .contains("artistName", "Untitled Artist")
                    .findFirst();
            if (query != null) {
                return query;
            } else {
                Artist newArtist = realm.createObject(Artist.class);
                newArtist.setArtistName("Untitled Artist");
                if (rhythmSong.getImageData() != null) {
                    newArtist.setCoverPath(rhythmSong.getSongLocation());
                }
                newArtist.setId(UUID.randomUUID().toString());
                return newArtist;
            }
        } else {
            Artist query = realm.where(Artist.class)
                    .contains("artistName", rhythmSong.getArtistTitle())
                    .findFirst();
            if (query != null) {
                return query;
            } else {
                Artist newArtist = realm.createObject(Artist.class);
                newArtist.setArtistName(rhythmSong.getArtistTitle());
                if (rhythmSong.getImageData() != null) {
                    newArtist.setCoverPath(rhythmSong.getSongLocation());
                }
                newArtist.setId(UUID.randomUUID().toString());
                return newArtist;
            }
        }
    }

    private static Album getOrCreateAlbum(Realm realm, Artist artistRecord, RhythmSong rhythmSong) {
        Album albumRecord = null;
        if (rhythmSong.getAlbumTitle() == null) {
            for (Album albumItem : artistRecord.getAlbums()) {
                if (albumItem.getAlbumTitle().equals("Untitled Album")) {
                    albumRecord = albumItem;
                }
            }
            if (albumRecord != null) {
                return albumRecord;
            } else {
                albumRecord = realm.createObject(Album.class);
                albumRecord.setAlbumTitle("Untitled Album");
                albumRecord.setId(UUID.randomUUID().toString());
                albumRecord.setArtistId(artistRecord.getId());
                if (rhythmSong.getImageData() != null) {
                    albumRecord.setCoverPath(rhythmSong.getSongLocation());
                }
                artistRecord.getAlbums().add(albumRecord);
                return albumRecord;
            }
        } else {
            for (Album albumItem : artistRecord.getAlbums()) {
                if (albumItem.getAlbumTitle().equals(rhythmSong.getAlbumTitle())) {
                    albumRecord = albumItem;
                }
            }
            if (albumRecord != null) {
                return albumRecord;
            } else {
                albumRecord = realm.createObject(Album.class);
                albumRecord.setAlbumTitle(rhythmSong.getAlbumTitle());
                albumRecord.setId(UUID.randomUUID().toString());
                albumRecord.setArtistId(artistRecord.getId());
                if (rhythmSong.getImageData() != null) {
                    albumRecord.setCoverPath(rhythmSong.getSongLocation());
                }
                artistRecord.getAlbums().add(albumRecord);
                return albumRecord;
            }
        }
    }

    private static void getOrCreateSong(Realm realm, Album albumRecord, String songTitle, long duration, String songPath) {
        Song songRecord = null;
        for (Song songItem : albumRecord.getSongs()) {
            if (songItem.getSongLocation().equals(songPath)) {
                songRecord = songItem;
            }
        }
        if (songRecord == null) {
            songRecord = realm.createObject(Song.class);
            songRecord.setId(UUID.randomUUID().toString());
            songRecord.setSongTitle(songTitle != null ? songTitle : "Untitled Song");
            songRecord.setAlbumId(albumRecord.getId());
            songRecord.setSongLocation(songPath);
            if (duration > 0) {
                songRecord.setSongDuration(duration);
            }
            albumRecord.getSongs().add(songRecord);
        }

    }

    public static List<Artist> allArtists(Context context) {
        Realm realm = Realm.getInstance(context);
        return realm.allObjects(Artist.class);
    }

    public static List<Song> getAllSongs(Context context) {
        Realm realm = Realm.getInstance(context);
        return realm.allObjects(Song.class);
    }

    private static List<Song> getLastPlayedSongs(Context context) {
        Realm realm = Realm.getInstance(context);
        RealmResults<Song> result = realm.where(Song.class).greaterThan("lastPlayed", 0).findAll();
        result.sort("lastPlayed", Sort.DESCENDING);
        return result;
    }

    private static List<Song> getMostPlayedSongs(Context context) {
        Realm realm = Realm.getInstance(context);
        RealmResults<Song> result = realm.where(Song.class).greaterThan("noOfPlayed", 0).findAll();
        result.sort("noOfPlayed", Sort.DESCENDING);
        return result;
    }

    public static List<Playlist> getPlayists(Context context) {
        Realm realm = Realm.getInstance(context);
        return realm.allObjects(Playlist.class);
    }

    public static Song getSongById(String id, Context context) {
        Realm realm = Realm.getInstance(context);
        realm.beginTransaction();
        Song song = realm.where(Song.class)
                .contains("id", id)
                .findFirst();
        realm.commitTransaction();
        realm.close();
        return song;
    }

    private static Album getAlbumById(String id, Context context) {
        Realm realm = Realm.getInstance(context);
        realm.beginTransaction();
        Album album = realm.where(Album.class)
                .contains("id", id)
                .findFirst();
        realm.commitTransaction();
        realm.close();
        return album;
    }

    public static Artist getArtistById(String id, Context context) {
        Realm realm = Realm.getInstance(context);
        realm.beginTransaction();
        Artist artist = realm.where(Artist.class)
                .contains("id", id)
                .findFirst();
        realm.commitTransaction();
        realm.close();
        return artist;
    }

    private static Playlist getPlaylistById(String id, Context context) {
        Realm realm = Realm.getInstance(context);
        realm.beginTransaction();
        Playlist playlist = realm.where(Playlist.class)
                .contains("id", id)
                .findFirst();
        realm.commitTransaction();
        realm.close();
        return playlist;
    }

    public static List<Song> getSongsFromList(MusicContent musicContent, Context context) {
        switch (musicContent.getContentType()) {
            case ARTIST:
                //TODO: get all songs from artist
                return getArtistById(musicContent.getId(), context).getAlbums().get(0).getSongs();
            case ALBUM:
                return getAlbumById(musicContent.getId(), context).getSongs();
            case PLAYLIST:
                return getPlaylistById(musicContent.getId(), context).getSongs();
            case MOST_PLAYED:
                return getMostPlayedSongs(context);
            case LAST_PLAYED:
                return getLastPlayedSongs(context);
        }

        return null;
    }

    public static void createPlaylist(String playlistName, Context context) {
        Realm realm = Realm.getInstance(context);
        realm.beginTransaction();

        Playlist playlistRecord = realm.createObject(Playlist.class);
        playlistRecord.setId(UUID.randomUUID().toString());
        playlistRecord.setPlaylistName(playlistName);

        realm.commitTransaction();
        realm.close();
    }

    public static void deletePlaylist(String playlistID, Context context) {
        Realm realm = Realm.getInstance(context);
        realm.beginTransaction();

        Playlist playlistToDelete = realm.where(Playlist.class)
                .equalTo("id", playlistID)
                .findFirst();
        playlistToDelete.removeFromRealm();
        realm.commitTransaction();
        realm.close();
    }

    public static void updateSongCount(String songId, Context context) {
        Realm realm = Realm.getInstance(context);
        realm.beginTransaction();
        Song song = realm.where(Song.class)
                .contains("id", songId)
                .findFirst();
        song.setNoOfPlayed(song.getNoOfPlayed() + 1);
        song.setLastPlayed(System.currentTimeMillis());

        realm.commitTransaction();
        realm.close();
    }

    public static void resetMusicStats(Context context) {
        Realm realm = Realm.getInstance(context);
        realm.beginTransaction();
        realm.where(Artist.class).findAll().clear();
        realm.where(Album.class).findAll().clear();
        realm.where(Song.class).findAll().clear();
        realm.where(Playlist.class).findAll().clear();
        realm.commitTransaction();
        realm.close();
    }
} public class PlayBackUtil {
    private static List<SongDTO> currentPlayList = null;
    private static int currentSongPosition = 0;
    private static MediaPlayer mediaPlayer = null;
    private static PlayMode currentPlayMode = PlayMode.NONE;
    private static RhythmSong currentSong;

    public static MediaPlayer getMediaPlayer() {
        return mediaPlayer;
    }

    public static MediaPlayer setMediaPlayer(Context context, String songLocation) {
        try {
            if (mediaPlayer != null) {
                if (mediaPlayer.isPlaying()) {
                    mediaPlayer.stop();
                }
                mediaPlayer.reset();
            }
            mediaPlayer = MediaPlayer.create(context, Uri.parse(songLocation));
            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            return mediaPlayer;
        } catch (Exception e) {
            Timber.e(e, "setMediaPlayer");
            mediaPlayer = MediaPlayer.create(context, Uri.parse(songLocation));
            mediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
            return mediaPlayer;
        }
    }

    public static List<SongDTO> getCurrentPlayList() {
        return currentPlayList;
    }

    public static void setCurrentPlayList(List<SongDTO> newPlayList) {
        currentPlayList = newPlayList;
    }

    public static int getCurrentSongPosition() {
        return currentSongPosition;
    }

    public static void setCurrentSongPosition(int newCurrentPosition) {
        currentSongPosition = newCurrentPosition;
    }

    public static PlayMode getCurrentPlayMode() {
        return currentPlayMode;
    }

    public static PlayMode getUpdateCurrentPlayMode(PlayMode newPlayMode) {
        if (newPlayMode == PlayMode.SHUFFLE) {
            if (currentPlayMode == PlayMode.NONE || currentPlayMode == PlayMode.SINGLE_REPEAT) {
                currentPlayMode = PlayMode.SHUFFLE;
            } else if (currentPlayMode == PlayMode.ALL_REPEAT) {
                currentPlayMode = PlayMode.SHUFFLE_REPEAT;
            } else if (currentPlayMode == PlayMode.SHUFFLE_REPEAT) {
                currentPlayMode = PlayMode.ALL_REPEAT;
            } else if (currentPlayMode == PlayMode.SHUFFLE) {
                currentPlayMode = PlayMode.NONE;
            }
        } else if (newPlayMode == PlayMode.REPEAT) {
            if (currentPlayMode == PlayMode.NONE) {
                currentPlayMode = PlayMode.SINGLE_REPEAT;
            } else if (currentPlayMode == PlayMode.SINGLE_REPEAT) {
                currentPlayMode = PlayMode.ALL_REPEAT;
            } else if (currentPlayMode == PlayMode.ALL_REPEAT) {
                currentPlayMode = PlayMode.NONE;
            } else if (currentPlayMode == PlayMode.SHUFFLE) {
                currentPlayMode = PlayMode.SHUFFLE_REPEAT;
            } else if (currentPlayMode == PlayMode.SHUFFLE_REPEAT) {
                currentPlayMode = PlayMode.SHUFFLE;
            }
        }
        return currentPlayMode;
    }

    public static RhythmSong getCurrentSong() {
        return currentSong;
    }

    public static void setCurrentSong(RhythmSong currentSong) {
        PlayBackUtil.currentSong = currentSong;
    }
} public enum PlayMode {
    NONE, REPEAT, SHUFFLE, SHUFFLE_REPEAT, SINGLE_REPEAT, ALL_REPEAT
} public class RhythmSong implements Parcelable {

    final private String artistTitle;
    final private String albumTitle;
    final private String trackTitle;
    final private byte[] imageData;
    final private long duration;
    final private String songLocation;

    private RhythmSong(RhythmSongBuilder builder) {
        this.artistTitle = builder.artistTitle;
        this.albumTitle = builder.albumTitle;
        this.trackTitle = builder.trackTitle;
        this.imageData = builder.imageData;
        this.duration = builder.duration;
        this.songLocation = builder.songLocation;
    }

    public String getArtistTitle() {
        return artistTitle;
    }

    public String getAlbumTitle() {
        return albumTitle;
    }

    public String getTrackTitle() {
        return trackTitle;
    }

    public byte[] getImageData() {
        return imageData;
    }

    public long getDuration() {
        return duration;
    }

    public String getSongLocation() {
        return songLocation;
    }

    public static class RhythmSongBuilder {
        private String artistTitle;
        private String albumTitle;
        private String trackTitle;
        private byte[] imageData;
        private long duration;
        private String songLocation;

        public RhythmSongBuilder artistTitle(String artistTitle) {
            this.artistTitle = artistTitle;
            return this;
        }

        public RhythmSongBuilder albumTitle(String albumTitle) {
            this.albumTitle = albumTitle;
            return this;
        }

        public RhythmSongBuilder trackTitle(String trackTitle) {
            this.trackTitle = trackTitle;
            return this;
        }

        public RhythmSongBuilder imageData(byte[] imageData) {
            this.imageData = imageData;
            return this;
        }

        public RhythmSongBuilder duration(long duration) {
            this.duration = duration;
            return this;
        }

        public RhythmSongBuilder songLocation(String songLocation) {
            this.songLocation = songLocation;
            return this;
        }

        public RhythmSong build() {
            return new RhythmSong(this);
        }
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.artistTitle);
        dest.writeString(this.albumTitle);
        dest.writeString(this.trackTitle);
        dest.writeByteArray(this.imageData);
        dest.writeFloat(this.duration);
        dest.writeString(this.songLocation);
    }

    protected RhythmSong(Parcel in) {
        this.artistTitle = in.readString();
        this.albumTitle = in.readString();
        this.trackTitle = in.readString();
        this.imageData = in.createByteArray();
        this.duration = in.readLong();
        this.songLocation = in.readString();
    }

    public static final Parcelable.Creator<RhythmSong> CREATOR = new Parcelable.Creator<RhythmSong>() {
        public RhythmSong createFromParcel(Parcel source) {
            return new RhythmSong(source);
        }

        public RhythmSong[] newArray(int size) {
            return new RhythmSong[size];
        }
    };

    @Override
    public String toString() {
        return "RhythmSong{" +
                "artistTitle='" + artistTitle + '\'' +
                ", albumTitle='" + albumTitle + '\'' +
                ", trackTitle='" + trackTitle + '\'' +
                ", duration=" + duration +
                ", songLocation='" + songLocation + '\'' +
                '}';
    }
} public class ViewUtils {
    public static void drawerClickListener(final Activity activity) {

        View.OnClickListener clickListener = new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int i = v.getId();
                if (i == R.id.browse_drawer_item) {
                    Intent browse = new Intent(activity, BrowseActivity.class);
                    activity.startActivity(browse);
                } else if (i == R.id.most_played_drawer_item) {
                    Intent mostPlayed = new Intent(activity, PlaylistActivity.class);
                    MusicContent musicContent = new MusicContent();
                    musicContent.setContentType(ContentType.MOST_PLAYED);
                    musicContent.setPlaylistName("Most Played");
                    mostPlayed.putExtra("musicContent", musicContent);
                    activity.startActivity(mostPlayed);
                } else if (i == R.id.last_played_drawer_item) {
                    Intent lastPlayed = new Intent(activity, PlaylistActivity.class);
                    MusicContent musicContent = new MusicContent();
                    musicContent.setContentType(ContentType.LAST_PLAYED);
                    musicContent.setPlaylistName("Last Played");
                    lastPlayed.putExtra("musicContent", musicContent);
                    activity.startActivity(lastPlayed);
                } else if (i == R.id.playlists_drawer_item) {
                    Intent playlists = new Intent(activity, PlaylistGridActivity.class);
                    activity.startActivity(playlists);
                } else if (i == R.id.now_playing_drawer_item) {
                    Intent playerIntent = new Intent(activity, SwipePlayerActivity.class);
                    playerIntent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP);
                    activity.startActivity(playerIntent);
                } else if (i == R.id.settings_drawer_item) {
                    Intent settings = new Intent(activity, RhythmPrefs.class);
                    activity.startActivity(settings);
                }
            }
        };

        activity.findViewById(R.id.browse_drawer_item).setOnClickListener(clickListener);
        activity.findViewById(R.id.most_played_drawer_item).setOnClickListener(clickListener);
        activity.findViewById(R.id.last_played_drawer_item).setOnClickListener(clickListener);
        activity.findViewById(R.id.playlists_drawer_item).setOnClickListener(clickListener);
        activity.findViewById(R.id.now_playing_drawer_item).setOnClickListener(clickListener);
        activity.findViewById(R.id.settings_drawer_item).setOnClickListener(clickListener);

        activity.findViewById(R.id.now_playing_drawer_item).setVisibility(PlayBackUtil.getMediaPlayer() != null ? View.VISIBLE : View.GONE);
    }
} public enum PlayMode {
    NONE, REPEAT, SHUFFLE, SHUFFLE_REPEAT, SINGLE_REPEAT, ALL_REPEAT
}
import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.view.GravityCompat;
import android.support.v4.view.ViewPager;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.TextView;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.wearable.DataMap;
import com.google.android.gms.wearable.Wearable;
import com.laithlab.rhythm.R;
import com.laithlab.rhythm.dto.SongDTO;
import com.laithlab.rhythm.fragment.SongFragment;
import com.laithlab.rhythm.fragment.SongFragmentCallback;
import com.laithlab.rhythm.service.Constants;
import com.laithlab.rhythm.service.SendToDataLayerThread;
import com.laithlab.rhythm.utils.MusicDataUtility;
import com.laithlab.rhythm.utils.PlayBackUtil;
import com.laithlab.rhythm.utils.PlayMode;
import com.laithlab.rhythm.utils.RhythmSong;
import com.laithlab.rhythm.utils.ViewUtils;
import java.util.Collections;
import java.util.List;
import static com.laithlab.rhythm.utils.PlayMode.*;
package com.laithlab.rhythm.activity;






public class SwipePlayerActivity extends RhythmActivity implements SongFragmentCallback, GoogleApiClient.ConnectionCallbacks,
        GoogleApiClient.OnConnectionFailedListener {

    private DrawerLayout drawerLayout;
    private Toolbar toolbar;
    private View tiltedView;
    private TextView artist;
    private TextView album;
    private ViewPager viewPager;
    private Menu menu;
    private View playerBackground;

    private boolean isWearConnected = false;
    private boolean changedSongFromNotification = false;
    public static String SONG_POSITION_PARAM = "songPosition";
    public static String SONGS_PARAM = "songs";
    private int songPosition;
    private List<SongDTO> songsList;

    private GoogleApiClient googleClient;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_swipe_player);
        LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, new IntentFilter(Constants.PLAYER));

        googleClient = new GoogleApiClient.Builder(this)
                .addApi(Wearable.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();

        toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        final ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            getSupportActionBar().setDisplayShowTitleEnabled(false);
            actionBar.setHomeAsUpIndicator(R.drawable.ic_menu_white_24dp);
            actionBar.setDisplayHomeAsUpEnabled(true);
        }

        tiltedView = findViewById(R.id.tilted_view);
        playerBackground = findViewById(R.id.player_background);

        drawerLayout = (DrawerLayout) findViewById(R.id.drawer_layout);
        drawerLayout.setStatusBarBackgroundColor(getResources().getColor(R.color.color_primary));
        viewPager = (ViewPager) findViewById(R.id.pager);

        artist = (TextView) findViewById(R.id.txt_artist);
        album = (TextView) findViewById(R.id.txt_album);

        Bundle extras = getIntent().getExtras();
        if (extras != null) {
            songPosition = extras.getInt(SONG_POSITION_PARAM);
            songsList = extras.getParcelableArrayList(SONGS_PARAM);
            PlayBackUtil.setCurrentPlayList(songsList);