/*
* Copyright 2015 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.nimingban.client;
import android.content.Context;
import android.os.AsyncTask;
import android.util.Log;
import com.alibaba.fastjson.JSON;
import com.hippo.nimingban.NMBApplication;
import com.hippo.nimingban.client.ac.ACEngine;
import com.hippo.nimingban.client.ac.data.ACPostStruct;
import com.hippo.nimingban.client.ac.data.ACReplyStruct;
import com.hippo.nimingban.client.data.Site;
import com.hippo.yorozuya.PriorityThreadFactory;
import com.hippo.yorozuya.SimpleHandler;
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 okhttp3.Call;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public class NMBClient {
public static final String TAG = NMBClient.class.getSimpleName();
public static final int METHOD_NOTICE = -6;
public static final int METHOD_CONVERT = -5;
public static final int METHOD_COMMON_POSTS = -4;
public static final int METHOD_DISC = -3;
public static final int METHOD_UPDATE = -2;
public static final int METHOD_GET_FORUM_LIST = -1;
public static final int METHOD_GET_COOKIE = 0;
public static final int METHOD_GET_POST_LIST = 1;
public static final int METHOD_GET_POST = 2;
public static final int METHOD_GET_REFERENCE = 3;
public static final int METHOD_REPLY = 4;
public static final int METHOD_GET_FEED = 5;
public static final int METHOD_ADD_FEED = 6;
public static final int METHOD_DEL_FEED = 7;
public static final int METHOD_CREATE_POST = 8;
public static final int METHOD_SEARCH = 10;
public static final int METHOD_GET_CDN_PATH = 11;
private final ThreadPoolExecutor mRequestThreadPool;
private final OkHttpClient mOkHttpClient;
public NMBClient(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 = NMBApplication.getOkHttpClient(context);
}
public void execute(NMBRequest request) {
if (!request.isCancelled()) {
Task task = new Task(request.method, request.site, request.callback);
task.executeOnExecutor(mRequestThreadPool, request.args);
request.task = task;
} else {
request.callback.onCancel();
}
}
public class Task extends AsyncTask<Object, Void, Object> {
private int mMethod;
private Site mSite;
private Callback mCallback;
private Call mCall;
private boolean mStop;
public Task(int method, Site site, Callback callback) {
mMethod = method;
mSite = site;
mCallback = callback;
}
public void stop() {
if (!mStop) {
mStop = true;
if (mCallback != null) {
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) {
if (mCall != null) {
mCall.cancel();
}
}
// Clear
mCall = null;
mCallback = null;
}
}
private Object getCommonPosts() throws Exception {
switch (mSite.getId()) {
case Site.AC:
Call call = ACEngine.prepareGetCommonPosts(mOkHttpClient);
if (!mStop) {
mCall = call;
return ACEngine.doGetCommonPosts(call);
} else {
throw new CancelledException();
}
default:
return new IllegalStateException("Can't detect site " + mSite);
}
}
private Object getForumList() throws Exception {
switch (mSite.getId()) {
case Site.AC:
Call call = ACEngine.prepareGetForumList(mOkHttpClient);
if (!mStop) {
mCall = call;
return ACEngine.doGetForumList(call);
} else {
throw new CancelledException();
}
default:
return new IllegalStateException("Can't detect site " + mSite);
}
}
private Object getCookie() throws Exception {
switch (mSite.getId()) {
case Site.AC:
Call call = ACEngine.prepareGetCookie(mOkHttpClient);
if (!mStop) {
mCall = call;
return ACEngine.doGetCookie(call);
} else {
throw new CancelledException();
}
default:
return new IllegalStateException("Can't detect site " + mSite);
}
}
private Object getPostList(Object... params) throws Exception {
switch (mSite.getId()) {
case Site.AC:
Call call = ACEngine.prepareGetPostList(mOkHttpClient, (String) params[0], (Integer) params[1]);
if (!mStop) {
mCall = call;
return ACEngine.doGetPostList(call);
} else {
throw new CancelledException();
}
default:
return new IllegalStateException("Can't detect site " + mSite);
}
}
private Object getPost(Object... params) throws Exception {
switch (mSite.getId()) {
case Site.AC:
Call call = ACEngine.prepareGetPost(mOkHttpClient, (String) params[0], (Integer) params[1]);
if (!mStop) {
mCall = call;
return ACEngine.doGetPost(call);
} else {
throw new CancelledException();
}
default:
return new IllegalStateException("Can't detect site " + mSite);
}
}
private Object getReference(Object... params) throws Exception {
switch (mSite.getId()) {
case Site.AC:
Call call = ACEngine.prepareGetReference(mOkHttpClient, (String) params[0]);
if (!mStop) {
mCall = call;
return ACEngine.doGetReference(call);
} else {
throw new CancelledException();
}
default:
return new IllegalStateException("Can't detect site " + mSite);
}
}
private Object reply(Object... params) throws Exception {
switch (mSite.getId()) {
case Site.AC:
Call call = ACEngine.prepareReply(mOkHttpClient, (ACReplyStruct) params[0]);
if (!mStop) {
mCall = call;
return ACEngine.doReply(call);
} else {
throw new CancelledException();
}
default:
return new IllegalStateException("Can't detect site " + mSite);
}
}
private Object getFeed(Object... params) throws Exception {
switch (mSite.getId()) {
case Site.AC:
Call call = ACEngine.prepareGetFeed(mOkHttpClient, (String) params[0], (Integer) params[1]);
if (!mStop) {
mCall = call;
return ACEngine.doGetFeed(call);
} else {
throw new CancelledException();
}
default:
return new IllegalStateException("Can't detect site " + mSite);
}
}
private Object addFeed(Object... params) throws Exception {
switch (mSite.getId()) {
case Site.AC:
Call call = ACEngine.prepareAddFeed(mOkHttpClient, (String) params[0], (String) params[1]);
if (!mStop) {
mCall = call;
return ACEngine.doAddFeed(call);
} else {
throw new CancelledException();
}
default:
return new IllegalStateException("Can't detect site " + mSite);
}
}
private Object delFeed(Object... params) throws Exception {
switch (mSite.getId()) {
case Site.AC:
Call call = ACEngine.prepareDelFeed(mOkHttpClient, (String) params[0], (String) params[1]);
if (!mStop) {
mCall = call;
return ACEngine.doDelFeed(call);
} else {
throw new CancelledException();
}
default:
return new IllegalStateException("Can't detect site " + mSite);
}
}
private Object createPost(Object... params) throws Exception {
switch (mSite.getId()) {
case Site.AC:
Call call = ACEngine.prepareCreatePost(mOkHttpClient, (ACPostStruct) params[0]);
if (!mStop) {
mCall = call;
return ACEngine.doCreatePost(call);
} else {
throw new CancelledException();
}
default:
return new IllegalStateException("Can't detect site " + mSite);
}
}
private Object search(Object... params) throws Exception {
switch (mSite.getId()) {
case Site.AC:
Call call = ACEngine.prepareSearch(mOkHttpClient, (String) params[0], (Integer) params[1]);
if (!mStop) {
mCall = call;
return ACEngine.doSearch(call);
} else {
throw new CancelledException();
}
default:
return new IllegalStateException("Can't detect site " + mSite);
}
}
private Object getCdnPath() throws Exception {
switch (mSite.getId()) {
case Site.AC:
Call call = ACEngine.prepareGetCdnPath(mOkHttpClient);
if (!mStop) {
mCall = call;
return ACEngine.doGetCdnPath(call);
} else {
throw new CancelledException();
}
default:
return new IllegalStateException("Can't detect site " + mSite);
}
}
@Override
protected Object doInBackground(Object... params) {
try {
switch (mMethod) {
case METHOD_NOTICE: {
Log.d(TAG, "http://cover.acfunwiki.org/nmb-notice.json");
Request request = new Request.Builder().url("http://cover.acfunwiki.org/nmb-notice.json").build();
Call call = mOkHttpClient.newCall(request);
if (!mStop) {
mCall = call;
Response response = call.execute();
Notice notice = JSON.parseObject(response.body().string(), Notice.class);
if (notice == null) {
throw new Exception("No notice");
}
return notice;
} else {
throw new CancelledException();
}
}
case METHOD_CONVERT: {
Call call = ConvertEngine.prepareConvert(mOkHttpClient, (String) params[0], (String) params[1]);
if (!mStop) {
mCall = call;
return ConvertEngine.doConvert(call);
} else {
throw new CancelledException();
}
}
case METHOD_COMMON_POSTS:
return getCommonPosts();
case METHOD_DISC:
return DiscEngine.spider(mOkHttpClient, (String) params[0], (String) params[1]);
case METHOD_UPDATE: {
Call call = UpdateEngine.prepareUpdate(mOkHttpClient);
if (!mStop) {
mCall = call;
return UpdateEngine.doUpdate(call);
} else {
throw new CancelledException();
}
}
case METHOD_GET_FORUM_LIST:
return getForumList();
case METHOD_GET_COOKIE:
return getCookie();
case METHOD_GET_POST_LIST:
return getPostList(params);
case METHOD_GET_POST:
return getPost(params);
case METHOD_GET_REFERENCE:
return getReference(params);
case METHOD_REPLY:
return reply(params);
case METHOD_GET_FEED:
return getFeed(params);
case METHOD_ADD_FEED:
return addFeed(params);
case METHOD_DEL_FEED:
return delFeed(params);
case METHOD_CREATE_POST:
return createPost(params);
case METHOD_SEARCH:
return search(params);
case METHOD_GET_CDN_PATH:
return getCdnPath();
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) {
if (!(result instanceof CancelledException)) {
if (result instanceof Exception) {
mCallback.onFailure((Exception) result);
} else {
mCallback.onSuccess(result);
}
} else {
// onCancel is called in stop
}
}
// Clear
mCall = null;
mCallback = null;
}
}
public interface Callback<E> {
void onSuccess(E result);
void onFailure(Exception e);
void onCancel();
}
}