package com.ideabag.playtunes.fragment;
import com.google.android.gms.analytics.HitBuilders;
import com.google.android.gms.analytics.Tracker;
import com.ideabag.playtunes.PlaylistManager;
import com.ideabag.playtunes.R;
import com.ideabag.playtunes.DragNDrop.DragListener;
import com.ideabag.playtunes.DragNDrop.DragNDropListView;
import com.ideabag.playtunes.DragNDrop.DropListener;
import com.ideabag.playtunes.activity.MainActivity;
import com.ideabag.playtunes.adapter.PlaylistsOneAdapter;
import com.ideabag.playtunes.database.MediaQuery;
import com.ideabag.playtunes.dialog.SongMenuDialogFragment;
import com.ideabag.playtunes.util.IMusicBrowser;
import com.ideabag.playtunes.util.TrackerSingleton;
import com.ideabag.playtunes.util.GAEvent.Categories;
import com.ideabag.playtunes.util.GAEvent.Playlist;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.database.ContentObserver;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.provider.MediaStore;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentTransaction;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.Toast;
import android.widget.ToggleButton;
public class PlaylistsOneFragment extends Fragment implements IMusicBrowser, AdapterView.OnItemClickListener {
public static final String TAG = "One Playlist Fragment";
public static final String STARRED_TAG = "Starred Playlist Fragment";
MainActivity mActivity;
private Tracker mTracker;
PlaylistsOneAdapter adapter;
private String PLAYLIST_ID = "";
private MenuItem menuItemEdit, menuItemDoneEditing;
private String mTitle, mSubtitle;
private DragNDropListView mListView;
private boolean isEditing = false;
private boolean isStarred = false;
private static final String KEY_POSTION = "position_y";
private static final String KEY_OFFSET = "offset_y";
protected int mSavedScrollOffset = 0;
protected int mSavedScrollListPosition = 0;
@Override public void setMediaID( String media_id ) {
PLAYLIST_ID = media_id;
}
@Override public String getMediaID() { return PLAYLIST_ID; }
@Override public void onSaveInstanceState( Bundle outState ) {
super.onSaveInstanceState( outState );
outState.putString( getString( R.string.key_state_media_id ), PLAYLIST_ID );
outState.putBoolean( getString( R.string.key_state_playlist_editing ), isEditing );
outState.putInt( KEY_POSTION, mSavedScrollListPosition );
outState.putInt( KEY_OFFSET, mSavedScrollOffset );
}
@Override public void onAttach( Activity activity ) {
super.onAttach( activity );
mActivity = ( MainActivity ) activity;
mTracker = TrackerSingleton.getDefaultTracker( mActivity );
// Set screen name.
mTracker.setScreenName( TAG );
mActivity.setActionbarTitle( null );
mActivity.setActionbarSubtitle( null );
MediaQuery mGetPlaylistName = new MediaQuery(
MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
new String[] {
MediaStore.Audio.Playlists.NAME,
MediaStore.Audio.Playlists._ID
},
MediaStore.Audio.Playlists._ID + " =?",
new String[] {
PLAYLIST_ID
},
null
);
MediaQuery.executeAsync( getActivity(), mGetPlaylistName, new MediaQuery.OnQueryCompletedListener() {
@Override public void onQueryCompleted(MediaQuery mQuery, Cursor mResult) {
if ( mResult != null && mResult.getCount() > 0 ) {
mResult.moveToFirst();
try {
mActivity.setActionbarTitle( mResult.getString( mResult.getColumnIndexOrThrow( MediaStore.Audio.Playlists.NAME ) ) );
} catch( Exception e ) {
mActivity.setActionbarTitle( null );
}
}
mListView.setSelectionFromTop( mSavedScrollListPosition, mSavedScrollOffset );
if ( mResult != null && !mResult.isClosed() ) {
mResult.close();
}
}
});
}
@SuppressLint("NewApi")
@Override public void onActivityCreated( Bundle savedInstanceState ) {
super.onActivityCreated( savedInstanceState );
if ( null != savedInstanceState ) {
PLAYLIST_ID = savedInstanceState.getString( getString( R.string.key_state_media_id ) );
isEditing = savedInstanceState.getBoolean( getString( R.string.key_state_playlist_editing ) );
mSavedScrollListPosition = savedInstanceState.getInt( KEY_POSTION );
mSavedScrollOffset = savedInstanceState.getInt( KEY_OFFSET );
}
setRetainInstance( true );
setHasOptionsMenu( true );
// Adapter is asyncronous
adapter = new PlaylistsOneAdapter( mActivity, PLAYLIST_ID, songMenuClickListener, new MediaQuery.OnQueryCompletedListener() {
@Override public void onQueryCompleted( MediaQuery mQuery, Cursor mResult ) {
mActivity.setActionbarSubtitle( mResult.getCount() + " " + ( mResult.getCount() == 1 ? getString( R.string.song_singular) : getString( R.string.songs_plural) ) );
mListView.setSelectionFromTop( mSavedScrollListPosition, mSavedScrollOffset );
mTracker.send( new HitBuilders.EventBuilder()
.setCategory( isStarred ? Categories.STARRED_PLAYLIST : Categories.PLAYLIST )
.setAction( Playlist.ACTION_SHOWLIST )
.setValue( adapter.getCount() )
.build());
}
} );
// Configure for editing (or not)
adapter.setEditing( isEditing );
mListView.setDraggingEnabled( isEditing );
if ( android.os.Build.VERSION.SDK_INT < 11 && android.os.Build.VERSION.SDK_INT > 8) {
mListView.setOverScrollMode( AbsListView.OVER_SCROLL_NEVER );
}
mListView.setDivider( getResources().getDrawable( R.drawable.list_divider ) );
mListView.setDividerHeight( 1 );
mListView.setSelector( R.drawable.list_item_background );
// Dumb thing to have a bottom divider shown
mListView.setFooterDividersEnabled( true );
mListView.addFooterView( new View( getActivity() ), null, true);
//
mListView.setAdapter( adapter );
mListView.setOnItemClickListener( this );
mListView.setOnItemLongClickListener( mSongMenuLongClickListener );
getActivity().getContentResolver().registerContentObserver(
MediaStore.Audio.Playlists.Members.getContentUri( "external", Long.parseLong( PLAYLIST_ID ) ), true, mediaStoreChanged );
getActivity().getContentResolver().registerContentObserver(
MediaStore.Audio.Playlists.Members.getContentUri( "external", Long.parseLong( new PlaylistManager( getActivity() ).createStarredIfNotExist() ) ), true, mediaStoreChanged );
mListView.setDropListener( mSongDropListener );
mListView.setDragListener( mSongDragListener );
}
@Override public View onCreateView( LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState ) {
mListView = new DragNDropListView( getActivity(), null );
return mListView;
}
@Override public void onPause() {
super.onPause();
saveScrollPosition();
}
@Override public void onResume() {
super.onResume();
mTracker.send( new HitBuilders.AppViewBuilder().build() );
}
@Override public void onDestroy() {
super.onDestroy();
setHasOptionsMenu( false );
getActivity().getContentResolver().unregisterContentObserver( mediaStoreChanged );
}
@Override public void onItemClick( AdapterView<?> adapterView, View v, int position, long id ) {
if ( adapter.isEditing ) {
Toast.makeText( getActivity(), getString( R.string.playlist_cant_play_when_editing ), Toast.LENGTH_SHORT ).show();
} else {
String playlistName = mActivity.getSupportActionBar().getTitle().toString();
mActivity.mBoundService.setPlaylist( adapter.getQuery(), playlistName, PlaylistsOneFragment.class, PLAYLIST_ID );
mActivity.mBoundService.setPlaylistPosition( position );
mActivity.mBoundService.play();
}
mTracker.send( new HitBuilders.EventBuilder()
.setCategory( isStarred ? Categories.STARRED_PLAYLIST : Categories.PLAYLIST )
.setAction( Playlist.ACTION_CLICK )
.setValue( position )
.build());
}
// if ( adapter.isEditing ) {
protected AdapterView.OnItemLongClickListener mSongMenuLongClickListener = new AdapterView.OnItemLongClickListener() {
@Override public boolean onItemLongClick( AdapterView<?> arg0, View v, int position, long id ) {
if ( adapter.isEditing ) {
Toast.makeText( getActivity(), getString( R.string.playlist_cant_play_when_editing ), Toast.LENGTH_SHORT ).show();
} else {
showSongMenuDialog( "" + id );
}
mTracker.send( new HitBuilders.EventBuilder()
.setCategory( isStarred ? Categories.STARRED_PLAYLIST : Categories.PLAYLIST )
.setAction( Playlist.ACTION_LONGCLICK )
.setValue( position )
.build());
return true;
}
};
private DropListener mSongDropListener = new DropListener() {
@Override public void onDrop( int from, int to ) {
mActivity.PlaylistManager.moveTrack( PLAYLIST_ID, from, to );
}
};
private DragListener mSongDragListener = new DragListener() {
@Override public void onStartDrag( int itemIndex, View itemView ) {
//android.util.Log.i( TAG, "" + itemView.getId() );
//itemView.requestFocus();
//itemView.requestFocusFromTouch();
}
@SuppressLint("NewApi")
@Override public void onDrag( int x, int y, ListView listView ) {
int mListHeight = listView.getHeight();
int mSafeYMin = mListHeight / 3;
int mSafeYMax = ( 2 * mListHeight ) / 3;
int mAmountToScrollY = 0;
if ( y < mSafeYMin ) {
int mYDiff = Math.abs( y - mSafeYMin );
// Scrolling up means a negative distance
mAmountToScrollY = -1 * calculateScrollYDistance( mYDiff, mSafeYMin );
//android.util.Log.i( TAG, "Scroll up: " + mAmountToScrollY );
} else if ( y > mSafeYMax ) {
int mYDiff = y - mSafeYMax;
mAmountToScrollY = calculateScrollYDistance( mYDiff, mSafeYMin );
//android.util.Log.i( TAG, "");
//android.util.Log.i( TAG, "Scroll down: " + mAmountToScrollY );
}
if ( mAmountToScrollY != 0 ) {
if ( android.os.Build.VERSION.SDK_INT >= 19 ) {
listView.scrollListBy( mAmountToScrollY );
} else {
//http://stackoverflow.com/questions/3014089/maintain-save-restore-scroll-position-when-returning-to-a-listview
int index = listView.getFirstVisiblePosition();
View v = listView.getChildAt(0);
int top = (v == null) ? 0 : v.getTop();
listView.setSelectionFromTop(index, ( top - mAmountToScrollY ) );
}
}
}
@Override public void onStopDrag( View itemView ) {
}
};
@Override public void onCreateOptionsMenu( Menu menu, MenuInflater inflater) {
inflater.inflate( R.menu.menu_playlist_one, menu );
menuItemEdit = menu.findItem( R.id.MenuPlaylistEdit );
menuItemDoneEditing = menu.findItem( R.id.MenuPlaylistDone );
menuItemDoneEditing.setVisible( isEditing );
menuItemEdit.setVisible( !isEditing );
}
@Override public void onPrepareOptionsMenu( Menu menu ) {
super.onPrepareOptionsMenu( menu );
if ( !mActivity.mShouldHideActionItems ) {
menuItemDoneEditing.setVisible( isEditing );
menuItemEdit.setVisible( !isEditing );
}
}
@Override public boolean onOptionsItemSelected( MenuItem item ) {
switch ( item.getItemId() ) {
case R.id.MenuPlaylistEdit:
isEditing = true;
menuItemDoneEditing.setVisible( isEditing );
menuItemEdit.setVisible( !isEditing );
adapter.setEditing( isEditing );
mListView.setDraggingEnabled( isEditing );
mTitle = (String) mActivity.getSupportActionBar().getTitle();
mSubtitle = (String) mActivity.getSupportActionBar().getSubtitle();
mActivity.setActionbarSubtitle( mTitle );
mActivity.setActionbarTitle( getActivity().getString( R.string.playlist_editing ) );
return true;
case R.id.MenuPlaylistDone:
isEditing = false;
menuItemDoneEditing.setVisible( isEditing );
menuItemEdit.setVisible( !isEditing );
adapter.setEditing( isEditing );
mListView.setDraggingEnabled( isEditing );
mActivity.setActionbarTitle( mTitle );
mActivity.setActionbarSubtitle( mSubtitle );
return true;
default:
return super.onOptionsItemSelected(item);
}
}
View.OnClickListener songMenuClickListener = new View.OnClickListener() {
@Override public void onClick( View v ) {
int viewID = v.getId();
String songID = "" + v.getTag( R.id.tag_song_id );
if ( viewID == R.id.StarButton ) {
ToggleButton starButton = ( ToggleButton ) v;
if ( starButton.isChecked() ) {
mActivity.PlaylistManager.addFavorite( songID );
//android.util.Log.i( "starred", songID );
} else {
mActivity.PlaylistManager.removeFavorite( songID );
//android.util.Log.i( "unstarred", songID );
}
} else if ( viewID == R.id.MenuButton ) {
showSongMenuDialog( songID );
} else if ( viewID == R.id.RemoveButton ) {
mActivity.PlaylistManager.removeSong( PLAYLIST_ID, songID );
Toast.makeText(getActivity(), getString( R.string.playlist_removed ), Toast.LENGTH_SHORT ).show();
}
}
};
protected void showSongMenuDialog( String songID ) {
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
SongMenuDialogFragment newFragment = new SongMenuDialogFragment();
newFragment.setMediaID( songID );
newFragment.show( ft, "dialog" );
}
ContentObserver mediaStoreChanged = new ContentObserver( new Handler() ) {
@Override public void onChange( boolean selfChange ) {
mActivity.runOnUiThread( new Runnable() {
@Override public void run() {
saveScrollPosition();
adapter.requery();
adapter.notifyDataSetChanged();
}
});
super.onChange( selfChange );
}
};
//
// The list is intended to scroll faster the closer the dragged item gets to the edge.
//
// The amount you scroll is calculated with f(x) = e^(b * x)
// Where b is the percentage inside of the scrolling zone you are times 5
//
//
private int calculateScrollYDistance( int diff, int listHeight ) {
//double mCoefficient = 0.00003 * listHeight;
double mCoefficient = (double) diff / listHeight;
double scrollAmount = Math.pow( Math.E, ( 5 * mCoefficient ) ) - 1;
//android.util.Log.i( TAG, "Coefficient: " + mCoefficient +" amount to scroll: " + scrollAmount );
return (int) scrollAmount;
}
private void saveScrollPosition() {
try {
if ( null != mListView ) {
mSavedScrollListPosition = mListView.getFirstVisiblePosition();
View v = mListView.getChildAt( 0 );
mSavedScrollOffset = ( v == null ? 0 : v.getTop() );
}
} catch( Exception e ) {
e.printStackTrace();
}
}
}