/*
* Copyright (c) 2013, Sorokin Alexander (uas.sorokin@gmail.com)
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. The names of the authors may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package com.uas.media.aimp.mobile;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import com.uas.media.aimp.AimpPlayerInstance;
import com.uas.media.aimp.R;
import com.uas.media.aimp.api.models.Playlist;
import com.uas.media.aimp.api.models.Song;
import com.uas.media.aimp.player.AimpPlayer;
import com.uas.media.aimp.player.StateObserver;
import com.uas.media.aimp.player.StateObserverViaHandler;
import com.uas.media.aimp.utils.InitErrorHandler;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* User: uas.sorokin@gmail.com
*/
public class PlaylistsListFragment extends Fragment {
public interface OnInitCompletedListener {
void onInitCompleted();
}
private ViewPager mPlsWrapper;
private AimpPlayer mAimpPlayer;
private PlaylistsAdapter mPlaylistsAdapter;
private StateObserver mStateObserver;
private ViewTreeObserver.OnGlobalLayoutListener mAdapterInitWaiter;
private OnInitCompletedListener mInitCompleteListener;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
ViewGroup wrapper = (ViewGroup) inflater.inflate(R.layout.mobile_pls_list, null, false);
//NOTICE Error appears when view's id is pls_wrapper
mPlsWrapper = (ViewPager) wrapper.findViewById(R.id.view_pager);
mAimpPlayer = AimpPlayerInstance.get();
mStateObserver = new StateObserverImpl();
mAimpPlayer.registerStateObserver(mStateObserver);
try {
initUi();
} catch (Exception ex) {
InitErrorHandler.handle(ex);
}
return wrapper;
}
@Override
public void onDestroyView() {
mAimpPlayer.unregisterStateObserver(mStateObserver);
mAimpPlayer = null;
super.onDestroyView();
}
public void setOnInitCompleteListener(OnInitCompletedListener listener) {
mInitCompleteListener = listener;
}
public boolean scrollTo(Playlist playlist, Song song) {
int playlistPosition = mAimpPlayer.getPlaylistPosition(playlist.getId());
int songPosition = playlist.findSongPosition(song);
mPlsWrapper.setCurrentItem(playlistPosition);
PlaylistFragment pf = mPlaylistsAdapter.getFragment(playlistPosition);
pf.scrollTo(songPosition);
return true;
}
protected void initUi() {
mAdapterInitWaiter = new AdapterInitWaiter();
mPlsWrapper.getViewTreeObserver().addOnGlobalLayoutListener(mAdapterInitWaiter);
updateAdapter();
}
protected void updateAdapter() {
// init params
Map<Integer, Integer> scrollPositions = new HashMap<Integer, Integer>();
int playlistPosition = mPlsWrapper.getCurrentItem();
if (mPlaylistsAdapter == null) {
Playlist currentPlaylist = mAimpPlayer.getCurrentPlaylist();
Song currentSong = mAimpPlayer.getCurrentSong();
if (currentSong != null) {
int songPosition = currentPlaylist.findSongPosition(currentSong);
scrollPositions.put(currentPlaylist.getId(), songPosition);
}
} else {
scrollPositions.putAll(mPlaylistsAdapter.getScrollPositions());
}
if (mPlaylistsAdapter == null || playlistPosition >= mAimpPlayer.getPlaylists().size()) {
playlistPosition = mAimpPlayer.getPlaylistPosition(mAimpPlayer.getCurrentPlaylist().getId());
}
// set up adapter
mPlaylistsAdapter = new PlaylistsAdapter(getChildFragmentManager(), mAimpPlayer.getPlaylists(), scrollPositions);
mPlsWrapper.setAdapter(mPlaylistsAdapter);
mPlsWrapper.setCurrentItem(playlistPosition);
}
class StateObserverImpl extends StateObserverViaHandler {
@Override
public void onPlaylistsInfoUpdated(List<Playlist> pls, Playlist currentPlaylist) {
updateAdapter();
}
}
class AdapterInitWaiter implements ViewTreeObserver.OnGlobalLayoutListener {
@Override
public void onGlobalLayout() {
mPlsWrapper.getViewTreeObserver().removeGlobalOnLayoutListener(mAdapterInitWaiter);
if (mInitCompleteListener != null) {
mInitCompleteListener.onInitCompleted();
}
}
}
class PlaylistsAdapter extends FragmentStatePagerAdapter {
private List<Playlist> mPlaylists;
private Map<Integer, PlaylistFragment> mFragments;
private Map<Integer, Integer> mPositions;
public PlaylistsAdapter(FragmentManager fm, List<Playlist> pls, Map<Integer, Integer> scrollPositions) {
super(fm);
mPlaylists = pls;
mFragments = new HashMap<Integer, PlaylistFragment>();
mPositions = new HashMap<Integer, Integer>();
mPositions.putAll(scrollPositions);
}
@Override
public Fragment getItem(int index) {
int playlistId = mPlaylists.get(index).getId();
Integer scrollPosition = mPositions.get(playlistId);
if (scrollPosition == null) {
scrollPosition = 0;
}
PlaylistFragment pf = PlaylistFragment.newInstance(playlistId, scrollPosition);
mFragments.put(index, pf);
return pf;
}
@Override
public int getCount() {
return mPlaylists.size();
}
@Override
public void destroyItem(ViewGroup container, int position, Object object) {
PlaylistFragment pf = mFragments.get(position);
mPositions.put(pf.getPlaylistId(), pf.getScrollPosition());
mFragments.remove(position);
super.destroyItem(container, position, object);
}
public PlaylistFragment getFragment(int index) {
return mFragments.get(index);
}
public Map<Integer, Integer> getScrollPositions() {
for (Map.Entry<Integer, PlaylistFragment> e: mFragments.entrySet()) {
mPositions.put(e.getValue().getPlaylistId(), e.getValue().getScrollPosition());
}
return mPositions;
}
public void clear() {
mFragments.clear();
mPositions.clear();
}
}
}