/*
* Copyright 2016 Hippo Seven
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.hippo.ehviewer.client;
import android.content.Context;
import android.os.AsyncTask;
import com.hippo.ehviewer.EhApplication;
import com.hippo.ehviewer.client.data.GalleryInfo;
import com.hippo.ehviewer.client.exception.CancelledException;
import com.hippo.yorozuya.SimpleHandler;
import com.hippo.yorozuya.thread.PriorityThreadFactory;
import java.io.File;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import okhttp3.Call;
import okhttp3.OkHttpClient;
public class EhClient {
public static final String TAG = EhClient.class.getSimpleName();
public static final int METHOD_SIGN_IN = 0;
public static final int METHOD_GET_GALLERY_LIST = 1;
public static final int METHOD_FILL_GALLERY_LIST_BY_API = 2;
public static final int METHOD_GET_GALLERY_DETAIL = 3;
public static final int METHOD_GET_PREVIEW_SET = 4;
public static final int METHOD_GET_RATE_GALLERY = 5;
public static final int METHOD_GET_COMMENT_GALLERY = 6;
public static final int METHOD_GET_GALLERY_TOKEN = 7;
public static final int METHOD_GET_FAVORITES = 8;
public static final int METHOD_ADD_FAVORITES = 9;
public static final int METHOD_ADD_FAVORITES_RANGE = 10;
public static final int METHOD_MODIFY_FAVORITES = 11;
public static final int METHOD_GET_TORRENT_LIST = 12;
public static final int METHOD_GET_WHATS_HOT = 13;
public static final int METHOD_GET_PROFILE = 14;
public static final int METHOD_VOTE_COMMENT = 15;
public static final int METHOD_IMAGE_SEARCH = 16;
public static final int METHOD_ARCHIVE_LIST = 17;
public static final int METHOD_DOWNLOAD_ARCHIVE = 18;
private final ThreadPoolExecutor mRequestThreadPool;
private final OkHttpClient mOkHttpClient;
public EhClient(Context context) {
int poolSize = 3;
BlockingQueue<Runnable> requestWorkQueue = new LinkedBlockingQueue<>();
ThreadFactory threadFactory = new PriorityThreadFactory(TAG,
android.os.Process.THREAD_PRIORITY_BACKGROUND);
mRequestThreadPool = new ThreadPoolExecutor(poolSize, poolSize,
1L, TimeUnit.SECONDS, requestWorkQueue, threadFactory);
mOkHttpClient = EhApplication.getOkHttpClient(context);
}
public void execute(EhRequest request) {
if (!request.isCancelled()) {
Task task = new Task(request.getMethod(), request.getCallback(), request.getEhConfig());
task.executeOnExecutor(mRequestThreadPool, request.getArgs());
request.task = task;
} else {
request.getCallback().onCancel();
}
}
public class Task extends AsyncTask<Object, Void, Object> {
private final int mMethod;
private Callback mCallback;
private EhConfig mEhConfig;
private final AtomicReference<Call> mCall = new AtomicReference<>();
private final AtomicBoolean mStop = new AtomicBoolean();
public Task(int method, Callback callback, EhConfig ehConfig) {
mMethod = method;
mCallback = callback;
mEhConfig = ehConfig;
}
// Called in Job thread
public void setCall(Call call) throws CancelledException {
if (mStop.get()) {
// Stopped Job thread
throw new CancelledException();
} else {
mCall.lazySet(call);
}
}
public EhConfig getEhConfig() {
return mEhConfig;
}
public void stop() {
if (!mStop.get()) {
mStop.lazySet(true);
if (mCallback != null) {
// TODO Avoid new runnable
final Callback finalCallback = mCallback;
SimpleHandler.getInstance().post(new Runnable() {
@Override
public void run() {
finalCallback.onCancel();
}
});
}
Status status = getStatus();
if (status == Status.PENDING) {
cancel(false);
} else if (status == Status.RUNNING) {
// It is running, cancel call if it is created
Call call = mCall.get();
if (call != null) {
call.cancel();
}
}
// Clear
mCallback = null;
mEhConfig = null;
mCall.lazySet(null);
}
}
@Override
@SuppressWarnings("unchecked")
protected Object doInBackground(Object... params) {
try {
switch (mMethod) {
case METHOD_SIGN_IN:
return EhEngine.signIn(this, mOkHttpClient, (String) params[0], (String) params[1]);
case METHOD_GET_GALLERY_LIST:
return EhEngine.getGalleryList(this, mOkHttpClient, (String) params[0]);
case METHOD_FILL_GALLERY_LIST_BY_API:
return EhEngine.fillGalleryListByApi(this, mOkHttpClient, (List<GalleryInfo>) params[0]);
case METHOD_GET_GALLERY_DETAIL:
return EhEngine.getGalleryDetail(this, mOkHttpClient, (String) params[0]);
case METHOD_GET_PREVIEW_SET:
return EhEngine.getPreviewSet(this, mOkHttpClient, (String) params[0]);
case METHOD_GET_RATE_GALLERY:
return EhEngine.rateGallery(this, mOkHttpClient, (Long) params[0], (String) params[1], (Long) params[2], (String) params[3], (Float) params[4]);
case METHOD_GET_COMMENT_GALLERY:
return EhEngine.commentGallery(this, mOkHttpClient, (String) params[0], (String) params[1]);
case METHOD_GET_GALLERY_TOKEN:
return EhEngine.getGalleryToken(this, mOkHttpClient, (Long) params[0], (String) params[1], (Integer) params[2]);
case METHOD_GET_FAVORITES:
return EhEngine.getFavorites(this, mOkHttpClient, (String) params[0], (Boolean) params[1]);
case METHOD_ADD_FAVORITES:
return EhEngine.addFavorites(this, mOkHttpClient, (Long) params[0], (String) params[1], (Integer) params[2], (String) params[3]);
case METHOD_ADD_FAVORITES_RANGE:
return EhEngine.addFavoritesRange(this, mOkHttpClient, (long[]) params[0], (String[]) params[1], (Integer) params[2]);
case METHOD_MODIFY_FAVORITES:
return EhEngine.modifyFavorites(this, mOkHttpClient, (String) params[0], (long[]) params[1], (Integer) params[2], (Boolean) params[3]);
case METHOD_GET_TORRENT_LIST:
return EhEngine.getTorrentList(this, mOkHttpClient, (String) params[0]);
case METHOD_GET_WHATS_HOT:
return EhEngine.getWhatsHot(this, mOkHttpClient);
case METHOD_GET_PROFILE:
return EhEngine.getProfile(this, mOkHttpClient);
case METHOD_VOTE_COMMENT:
return EhEngine.voteComment(this, mOkHttpClient, (Long) params[0], (String) params[1], (Long) params[2], (String) params[3], (Long) params[4], (Integer) params[5]);
case METHOD_IMAGE_SEARCH:
return EhEngine.imageSearch(this, mOkHttpClient, (File) params[0], (Boolean) params[1], (Boolean) params[2], (Boolean) params[3]);
case METHOD_ARCHIVE_LIST:
return EhEngine.getArchiveList(this, mOkHttpClient, (String) params[0]);
case METHOD_DOWNLOAD_ARCHIVE:
return EhEngine.downloadArchive(this, mOkHttpClient, (Long) params[0], (String) params[1], (String) params[2], (String) params[3]);
default:
return new IllegalStateException("Can't detect method " + mMethod);
}
} catch (Exception e) {
return e;
}
}
@SuppressWarnings("unchecked")
@Override
protected void onPostExecute(Object result) {
if (mCallback != null) {
//noinspection StatementWithEmptyBody
if (!(result instanceof CancelledException)) {
if (result instanceof Exception) {
mCallback.onFailure((Exception) result);
} else {
mCallback.onSuccess(result);
}
} else {
// onCancel is called in stop
}
}
// Clear
mCallback = null;
mEhConfig = null;
mCall.lazySet(null);
}
}
public interface Callback<E> {
void onSuccess(E result);
void onFailure(Exception e);
void onCancel();
}
}