/*
* Created by Angel Leon (@gubatron), Alden Torres (aldenml)
* Copyright (c) 2011-2014, FrostWire(R). All rights reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.bt.download.android.gui.tasks;
import com.bt.download.android.R;
import com.bt.download.android.gui.activities.MainActivity;
import com.bt.download.android.gui.dialogs.ConfirmListDialog;
import com.bt.download.android.gui.util.UIUtils;
import com.bt.download.android.gui.views.AbstractListAdapter;
import com.bt.download.android.gui.views.ContextTask;
import com.bt.download.android.util.ImageUtils;
import com.frostwire.logging.Logger;
import com.frostwire.search.SearchResult;
import com.frostwire.search.soundcloud.SoundCloudRedirectResponse;
import com.frostwire.search.soundcloud.SoundcloudItem;
import com.frostwire.search.soundcloud.SoundcloudPlaylist;
import com.frostwire.search.soundcloud.SoundcloudSearchResult;
import com.frostwire.util.HttpClientFactory;
import com.frostwire.util.JsonUtils;
import com.frostwire.util.Ref;
import com.frostwire.util.StringUtils;
import android.content.Context;
import android.view.View;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
/*
* @author aldenml
* @author gubatron
*/
public final class DownloadSoundcloudFromUrlTask extends ContextTask<List<SoundcloudSearchResult>> {
@SuppressWarnings("unused")
private static final Logger LOG = Logger.getLogger(DownloadSoundcloudFromUrlTask.class);
private final String soundcloudUrl;
private WeakReference<ConfirmSoundcloudDownloadDialog> dlgRef;
public DownloadSoundcloudFromUrlTask(Context ctx, String soundcloudUrl) {
super(ctx);
this.soundcloudUrl = soundcloudUrl;
}
private ConfirmSoundcloudDownloadDialog createConfirmListDialog(Context ctx, List<SoundcloudSearchResult> results) {
String title = ctx.getString(R.string.confirm_download);
String whatToDownload = ctx.getString((results.size() > 1) ? R.string.playlist : R.string.track);
String totalSize = UIUtils.getBytesInHuman(getTotalSize(results));
String text = ctx.getString(R.string.are_you_sure_you_want_to_download_the_following, whatToDownload, totalSize);
//ConfirmListDialog
ConfirmSoundcloudDownloadDialog dlg = ConfirmSoundcloudDownloadDialog.newInstance(title, text, results, new OnStartDownloadsClickListener(ctx, results));
return dlg;
}
private long getTotalSize(List<SoundcloudSearchResult> results) {
long totalSizeInBytes = 0;
for (SoundcloudSearchResult sr : results) {
totalSizeInBytes += sr.getSize();
}
return totalSizeInBytes;
}
public static void startDownloads(Context ctx, List<? extends SearchResult> srs) {
if (srs!=null && !srs.isEmpty()) {
for (SearchResult sr : srs) {
StartDownloadTask task = new StartDownloadTask(ctx, sr);
task.execute();
}
UIUtils.showTransfersOnDownloadStart(ctx);
}
}
@Override
protected void onPostExecute(Context ctx, List<SoundcloudSearchResult> results) {
if (!results.isEmpty()) {
MainActivity activity = (MainActivity) ctx;
ConfirmSoundcloudDownloadDialog dlg = createConfirmListDialog(ctx, results);
dlgRef = new WeakReference<ConfirmSoundcloudDownloadDialog>(dlg);
dlg.show(activity.getFragmentManager());
}
}
public void dismissDialog() {
if (Ref.alive(dlgRef)) {
dlgRef.get().dismiss();
}
}
@Override
protected List<SoundcloudSearchResult> doInBackground() {
final List<SoundcloudSearchResult> scResults = new ArrayList<SoundcloudSearchResult>();
//MOCK TEST FOR WHEN PHONE HAS NO INTERNET ACCESS.
/*
if (true) {
SoundcloudItem sItem = new SoundcloudItem();
for (int i=0; i < 10; i++) {
sItem.artwork_url="http://dummy.com";
sItem.created_at="2014-03-22";
sItem.download_url="http://url";
sItem.duration=334443;
sItem.original_content_size=(i%2==0) ? 1122332: 16200234;
sItem.title= (i % 2 == 0) ? "Dummy Title that is a bit longer than usual and perhaps might not fit" : "another one short";
sItem.uri="http://uri.com";
sItem.id=i;
scResults.add(new SoundcloudSearchResult(sItem,"someClient","someAppId"));
}
return scResults;
}*/
//resolve track information using http://api.soundcloud.com/resolve?url=<url>&client_id=b45b1aa10f1ac2941910a7f0d10f8e28
final String clientId="b45b1aa10f1ac2941910a7f0d10f8e28";
final String appVersion="dd9d3970";
try {
String url = soundcloudUrl;
if (soundcloudUrl.contains("?in=")) {
url = soundcloudUrl.substring(0, url.indexOf("?in="));
}
final String resolveURL = "http://api.soundcloud.com/resolve.json?url="+url+"&client_id="+clientId+"&app_version="+appVersion;;
//LOG.debug("DownloadSoundcloudFromUrlTask.resolveURL: " + resolveURL);
//LOG.debug("DownloadSoundcloudFromUrlTask.json >> ");
final String json = HttpClientFactory.newInstance().get(resolveURL,10000);
//LOG.debug(json);
//LOG.debug("EOF DownloadSoundcloudFromUrlTask.json");
if (json.contains("\"status\":\"30")) {
try {
System.out.println("Soundcloud Redirection! >> " + json);
final SoundCloudRedirectResponse redirectResponse = JsonUtils.toObject(json, SoundCloudRedirectResponse.class);
final String redirectedJson = HttpClientFactory.newInstance().get(redirectResponse.location,10000);
//System.out.println(redirectedJson);
downloadSetOrTrack(scResults, clientId, appVersion, redirectedJson);
} catch (Throwable t) {
t.printStackTrace();
}
} else {
downloadSetOrTrack(scResults, clientId, appVersion, json);
}
} catch (Throwable e) {
e.printStackTrace();
}
return scResults;
}
private void downloadSetOrTrack(final List<SoundcloudSearchResult> scResults, final String clientId, final String appVersion, final String json) {
if (soundcloudUrl.contains("/sets/")) {
downloadSet(scResults, clientId, appVersion, json);
} else {
downloadTrack(scResults, clientId, appVersion, json);
}
}
private void downloadTrack(final List<SoundcloudSearchResult> scResults, final String clientId, final String appVersion, final String json) {
//download single track
final SoundcloudItem scItem = JsonUtils.toObject(json, SoundcloudItem.class);
if (scItem != null) {
scResults.add(new SoundcloudSearchResult(scItem, clientId, appVersion));
}
}
private void downloadSet(final List<SoundcloudSearchResult> scResults, final String clientId, final String appVersion, final String json) {
//download a whole playlist
final SoundcloudPlaylist playlist = JsonUtils.toObject(json, SoundcloudPlaylist.class);
if (playlist != null && playlist.tracks != null) {
for (SoundcloudItem scItem : playlist.tracks) {
scResults.add(new SoundcloudSearchResult(scItem, clientId, appVersion));
}
}
}
private static class SimpleSoundcloudSearchResultAdapter extends AbstractListAdapter<SoundcloudSearchResult> {
public SimpleSoundcloudSearchResultAdapter(Context context, List<SoundcloudSearchResult> list) {
super(context, R.layout.list_item_track_confirmation_dialog, list);
}
@Override
protected void populateView(View view, SoundcloudSearchResult sr) {
TextView trackTitle = findView(view, R.id.list_item_track_confirmation_dialog_track_title);
trackTitle.setText(sr.getDisplayName());
TextView trackSizeInHuman = findView(view, R.id.list_item_track_confirmation_dialog_file_size_in_human);
trackSizeInHuman.setText(UIUtils.getBytesInHuman(sr.getSize()));
if (!StringUtils.isNullOrEmpty(sr.getThumbnailUrl())) {
ImageView imageView = findView(view, R.id.list_item_track_confirmation_dialog_art);
ImageUtils.load(sr.getThumbnailUrl(), imageView);
}
}
}
private static class OnStartDownloadsClickListener implements View.OnClickListener {
private final WeakReference<Context> ctxRef;
private final WeakReference<List<SoundcloudSearchResult>> resultsRef;
private WeakReference<ConfirmSoundcloudDownloadDialog> dlgRef;
public OnStartDownloadsClickListener(Context ctx, List<SoundcloudSearchResult> results) {
ctxRef = new WeakReference<Context>(ctx);
resultsRef = new WeakReference<List<SoundcloudSearchResult>>(results);
}
public void setDialog(ConfirmSoundcloudDownloadDialog dlg){
dlgRef = new WeakReference<ConfirmSoundcloudDownloadDialog>(dlg);
}
@Override
public void onClick(View v) {
if (Ref.alive(ctxRef)&& Ref.alive(resultsRef)) {
//TODO: gotta figure out how the parent dialog class
//will interact with the adapter (in a generic way)
//to filter out the List<T> when we have checkboxes.
startDownloads(ctxRef.get(), resultsRef.get());
if (Ref.alive(dlgRef)){
dlgRef.get().dismiss();
}
}
}
}
private static class SoundcloudSearchResultList {
List<SoundcloudSearchResult> listData;
}
public static class ConfirmSoundcloudDownloadDialog extends ConfirmListDialog<SimpleSoundcloudSearchResultAdapter,SoundcloudSearchResult> {
public ConfirmSoundcloudDownloadDialog() {
super();
}
public static ConfirmSoundcloudDownloadDialog newInstance(String dialogTitle, String dialogText, List<SoundcloudSearchResult> listData, OnStartDownloadsClickListener onYesListener) {
ConfirmSoundcloudDownloadDialog dlg = new ConfirmSoundcloudDownloadDialog();
SoundcloudSearchResultList srList = new SoundcloudSearchResultList();
srList.listData = listData;
dlg.prepareArguments(dialogTitle, dialogText, JsonUtils.toJson(srList));
dlg.setOnYesListener(onYesListener);
return dlg;
}
@Override
protected List<SoundcloudSearchResult> initListAdapter(final ListView listView, String listDataInJSON) {
SoundcloudSearchResultList srList = JsonUtils.toObject(listDataInJSON, SoundcloudSearchResultList.class);
listView.setAdapter(new SimpleSoundcloudSearchResultAdapter(getActivity(), srList.listData));
return srList.listData;
}
@Override
protected OnStartDownloadsClickListener createOnYesListener(List<SoundcloudSearchResult> listData) {
OnStartDownloadsClickListener listener = new OnStartDownloadsClickListener(getActivity(), listData);
listener.setDialog(this);
return listener;
}
}
}