package com.quinn.githubknife.interactor;
import android.content.Context;
import android.util.Log;
import com.quinn.githubknife.R;
import com.quinn.githubknife.account.GitHubAccount;
import com.quinn.githubknife.listener.OnLoadItemListListener;
import com.quinn.githubknife.model.GithubService;
import com.quinn.githubknife.model.RetrofitUtil;
import com.quinn.httpknife.github.Branch;
import com.quinn.httpknife.github.Event;
import com.quinn.httpknife.github.RepoSearch;
import com.quinn.httpknife.github.Repository;
import com.quinn.httpknife.github.Tree;
import com.quinn.httpknife.github.TrendingRepo;
import com.quinn.httpknife.github.User;
import com.quinn.httpknife.github.UserSearch;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import retrofit.Call;
import retrofit.Callback;
import retrofit.Response;
import retrofit.Retrofit;
import rx.Observable;
import rx.Observer;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;
/**
* Created by Quinn on 7/20/15.
*/
public class FindItemsInteractorImpl implements FindItemsInteractor {
private final static String TAG = "FindItemsInteractor";
private final static int LOAD_MORE_FAIL = 3;
private final static int LOAD_FIRST_FAIL = 2;
private final static int LOAD_SUCCESS = 1;
private GitHubAccount gitHubAccount;
private OnLoadItemListListener listener;
private GithubService service;
private Context context;
public FindItemsInteractorImpl(Context context, final OnLoadItemListListener listener) {
this.context = context;
this.service = RetrofitUtil.getJsonRetrofitInstance(context).create(GithubService.class);
this.gitHubAccount = GitHubAccount.getInstance(context);
this.listener = listener;
}
@Override
public void loadFollowerings(final String user, final int page) {
service.follwerings(user, String.valueOf(page))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Response<List<User>>>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
handleFailure(page);
}
@Override
public void onNext(Response<List<User>> response) {
RetrofitUtil.printResponse(response);
if (response.code() == 401) {
gitHubAccount.invalidateToken(RetrofitUtil.token);
loadFollowerings(user,page);
} else if (response.isSuccess()) {
listener.onFinished(response.body());
} else {
handleFailure(page);
}
}
});
}
@Override
public void loadFollwers(final String user, final int page) {
service.followers(user, String.valueOf(page))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Subscriber<Response<List<User>>>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
handleFailure(page);
}
@Override
public void onNext(Response<List<User>> response) {
RetrofitUtil.printResponse(response);
if (response.code() == 401) {
gitHubAccount.invalidateToken(RetrofitUtil.token);
loadFollwers(user, page);
} else if (response.isSuccess()) {
listener.onFinished(response.body());
} else {
handleFailure(page);
}
}
});
}
@Override
public void loadAuthUser() {
}
@Override
public void loadAuthRepos() {
}
@Override
public void loadRepo(final String user, final int page) {
Call<List<Repository>> call = service.userRepo(user, String.valueOf(page));
call.enqueue(new Callback<List<Repository>>() {
@Override
public void onResponse(Response<List<Repository>> response, Retrofit retrofit) {
RetrofitUtil.printResponse(response);
if (response.code() == 401) {
gitHubAccount.invalidateToken(RetrofitUtil.token);
loadRepo(user, page);
} else if (response.isSuccess()) {
listener.onFinished(response.body());
} else {
handleFailure(page);
}
}
@Override
public void onFailure(Throwable t) {
handleFailure(page);
}
});
}
@Override
public void loadStarredRepo(final String user, final int page) {
Call<List<Repository>> call = service.starredRepo(user, String.valueOf(page));
call.enqueue(new Callback<List<Repository>>() {
@Override
public void onResponse(Response<List<Repository>> response, Retrofit retrofit) {
RetrofitUtil.printResponse(response);
if (response.code() == 401) {
gitHubAccount.invalidateToken(RetrofitUtil.token);
loadStarredRepo(user, page);
} else if (response.isSuccess()) {
listener.onFinished(response.body());
} else {
handleFailure(page);
}
}
@Override
public void onFailure(Throwable t) {
handleFailure(page);
}
});
}
@Override
public void loadReceivedEvents(final String user, final int page) {
Call<List<Event>> call = service.receivedEvent(user, String.valueOf(page));
call.enqueue(new Callback<List<Event>>() {
@Override
public void onResponse(Response<List<Event>> response, Retrofit retrofit) {
RetrofitUtil.printResponse(response);
if (response.code() == 401) {
gitHubAccount.invalidateToken(RetrofitUtil.token);
loadReceivedEvents(user, page);
} else if (response.isSuccess()) {
listener.onFinished(response.body());
} else {
handleFailure(page);
}
}
@Override
public void onFailure(Throwable t) {
handleFailure(page);
}
});
}
@Override
public void loadUserEvents(final String user, final int page) {
Call<List<Event>> call = service.publicEvent(user, String.valueOf(page));
call.enqueue(new Callback<List<Event>>() {
@Override
public void onResponse(Response<List<Event>> response, Retrofit retrofit) {
RetrofitUtil.printResponse(response);
if (response.code() == 401) {
gitHubAccount.invalidateToken(RetrofitUtil.token);
loadUserEvents(user, page);
} else if (response.isSuccess()) {
listener.onFinished(response.body());
} else {
handleFailure(page);
}
}
@Override
public void onFailure(Throwable t) {
handleFailure(page);
}
});
}
@Override
public void loadRepoEvents(String user, String repo, int page) {
}
@Override
public void loadStargazers(final String owner, final String repo, final int page) {
final Call<List<User>> call = service.stargazers(owner, repo,String.valueOf(page));
call.enqueue(new Callback<List<User>>() {
@Override
public void onResponse(Response<List<User>> response, Retrofit retrofit) {
RetrofitUtil.printResponse(response);
if (response.code() == 401) {
gitHubAccount.invalidateToken(RetrofitUtil.token);
loadStargazers(owner, repo, page);
} else if (response.isSuccess()) {
listener.onFinished(response.body());
} else {
handleFailure(page);
}
}
@Override
public void onFailure(Throwable t) {
handleFailure(page);
}
});
}
@Override
public void loadForkers(final String owner, final String repo, final int page) {
final Call<List<User>> call = service.forkers(owner, repo, String.valueOf(page));
call.enqueue(new Callback<List<User>>() {
@Override
public void onResponse(Response<List<User>> response, Retrofit retrofit) {
RetrofitUtil.printResponse(response);
if (response.code() == 401) {
gitHubAccount.invalidateToken(RetrofitUtil.token);
loadForkers(owner, repo, page);
} else if (response.isSuccess()) {
listener.onFinished(response.body());
} else {
handleFailure(page);
}
}
@Override
public void onFailure(Throwable t) {
handleFailure(page);
}
});
}
@Override
public void loadCollaborators(final String owner, final String repo, final int page) {
final Call<List<User>> call = service.collaborators(owner, repo, String.valueOf(page));
call.enqueue(new Callback<List<User>>() {
@Override
public void onResponse(Response<List<User>> response, Retrofit retrofit) {
RetrofitUtil.printResponse(response);
if (response.code() == 401) {
gitHubAccount.invalidateToken(RetrofitUtil.token);
loadCollaborators(owner, repo, page);
} else if (response.isSuccess()) {
listener.onFinished(response.body());
} else {
handleFailure(page);
}
}
@Override
public void onFailure(Throwable t) {
handleFailure(page);
}
});
}
@Override
public void loadTree(final String owner, final String repo, final String sha) {
final Call<Tree> call = service.getTree(owner, repo, sha);
call.enqueue(new Callback<Tree>() {
@Override
public void onResponse(Response<Tree> response, Retrofit retrofit) {
RetrofitUtil.printResponse(response);
if (response.code() == 401) {
gitHubAccount.invalidateToken(RetrofitUtil.token);
loadTree(owner, repo, sha);
} else if (response.isSuccess()) {
listener.onFinished(response.body().getTree());
} else {
handleFailure();
}
}
@Override
public void onFailure(Throwable t) {
handleFailure();
}
});
}
@Override
public void searchUsers(final List<String> keywords, final int page) {
StringBuilder keywordsParams = new StringBuilder();
for (int i = 0; i < keywords.size(); i++) {
if (i != keywords.size() - 1)
keywordsParams.append(keywords.get(i) + "+");
else
keywordsParams.append(keywords.get(i));
}
final Call<UserSearch> call = service.searchUser(keywordsParams.toString(), String.valueOf(page));
call.enqueue(new Callback<UserSearch>() {
@Override
public void onResponse(Response<UserSearch> response, Retrofit retrofit) {
RetrofitUtil.printResponse(response);
if (response.code() == 401) {
gitHubAccount.invalidateToken(RetrofitUtil.token);
searchUsers(keywords, page);
} else if (response.isSuccess()) {
List<User> users = response.body().getItems();
User user = new User();
user.setFollowers(response.body().getTotal_count());
users.add(0, user);
listener.onFinished(users);
} else {
handleFailure(page);
}
}
@Override
public void onFailure(Throwable t) {
handleFailure(page);
}
});
}
@Override
public void searchRepos(final List<String> keywords, final int page) {
StringBuilder keywordsParams = new StringBuilder();
for (int i = 0; i < keywords.size(); i++) {
if (i != keywords.size() - 1)
keywordsParams.append(keywords.get(i) + "+");
else
keywordsParams.append(keywords.get(i));
}
final Call<RepoSearch> call = service.searchRepo(keywordsParams.toString(), String.valueOf(page));
call.enqueue(new Callback<RepoSearch>() {
@Override
public void onResponse(Response<RepoSearch> response, Retrofit retrofit) {
RetrofitUtil.printResponse(response);
if (response.code() == 401) {
gitHubAccount.invalidateToken(RetrofitUtil.token);
searchUsers(keywords, page);
} else if (response.isSuccess()) {
List<Repository> repos = response.body().getItems();
Repository repo = new Repository();
repo.setForks_count(response.body().getTotal_count());
repos.add(0,repo);
listener.onFinished(repos);
} else {
handleFailure(page);
}
}
@Override
public void onFailure(Throwable t) {
handleFailure(page);
}
});
}
@Override
public void loadBranches(final String owner, final String repo) {
final Call<List<Branch>> call = service.getBranches(owner, repo);
call.enqueue(new Callback<List<Branch>>() {
@Override
public void onResponse(Response<List<Branch>> response, Retrofit retrofit) {
RetrofitUtil.printResponse(response);
if (response.code() == 401) {
gitHubAccount.invalidateToken(RetrofitUtil.token);
loadBranches(owner, repo);
} else if (response.isSuccess()) {
listener.onFinished(response.body());
} else {
handleFailure();
}
}
@Override
public void onFailure(Throwable t) {
handleFailure();
}
});
}
public void trendingRepos(final String url, final TrendingRepo.SINCE_TYPE sinceType){
Observable.create(new Observable.OnSubscribe<List<TrendingRepo>>() {
@Override
public void call(Subscriber<? super List<TrendingRepo>> subscriber) {
// request
ArrayList<TrendingRepo> repos = new ArrayList<>();
try {
Log.i(TAG, "trendingRepos URL " + url);
Document doc = Jsoup.connect(url).get();
Elements elements = doc.getElementsByClass("repo-list");
Log.i(TAG, "elements" + elements.size());
Log.i(TAG, "childNodeSize" + elements.get(0).childNodeSize());
Log.i(TAG, "children" + elements.get(0).children().size());
elements = elements.get(0).children();
TrendingRepo repo;
for (Element element : elements) {
Log.i(TAG, "elements = " + element);
repo = new TrendingRepo();
Element hrefElement = element.child(0);
String href = hrefElement.getElementsByAttribute("href").get(0).attr("href");
Log.i(TAG, "href = " + href);
repo.setFull_name(href.substring(1));
String[] splits = href.split("/");
repo.setName(splits[2]);
User owner = new User();
owner.setLogin(splits[1]);
repo.setOwner(owner);
//可能没有despElement而直接紧接着newStarsElement
Element despElement = element.child(2);
String desp = despElement.text();
Log.i(TAG, "desp = " + desp);
repo.setDescription(desp);
// if(despElement.className().equals("repo-list-description")) {
//
// Element newStarsElement = despElement.nextElementSibling();
// starsDetail = newStarsElement.text();
// Log.i(TAG, "starsDetial = " + starsDetail);
// } else {
// starsDetail = despElement.text();
// Log.i(TAG, "starsDetial = " + starsDetail);
// }
// Element langElement = element.child(3).child(2);
Element starElement = element.child(3).children().last();
Log.i(TAG, "starElement " + starElement.text());
// Log.i(TAG, "langElement " + langElement.text());
String starsDetail= starElement.text();
starsDetail = starsDetail.replace(",", "");
String lang = "";
if(element.child(3).children().size() > 4) {
Element langElement = element.child(3).children().get(1);
lang = langElement.text();
}
//正则解析语言、Star数量
Pattern patternLanguage = Pattern.compile("[A-Za-z|+]{1,}"); //头个单词就是语言类别
Pattern patternStarNum = Pattern.compile("[0-9]{1,}"); //头个数字就是Star数量
Matcher matcherLanguage = patternLanguage.matcher(starsDetail);
Matcher matcherStarNum = patternStarNum.matcher(starsDetail);
repo.setSince_type(sinceType);
if (matcherStarNum.find()) {
repo.setAddStars(Integer.parseInt(matcherStarNum.group().trim()));
} else {
Log.i(TAG, "matcherStarNum.find fail" + starsDetail);
}
repo.setLanguage(lang);
repos.add(repo);
}
subscriber.onNext(repos);
subscriber.onCompleted();
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG, "error = " + e.toString());
subscriber.onError(e);
}
}
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<List<TrendingRepo>>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
listener.onError(true, context.getString(R.string.network_error));
}
@Override
public void onNext(List<TrendingRepo> trendingRepos) {
listener.onFinished(trendingRepos);
}
});
}
@Override
public void trendingUsers(String keywords, TrendingRepo.SINCE_TYPE sinceType){
}
public void handleFailure(int page){
if (page == 1) {
listener.onError(true, context.getResources().getString(R.string.fail_load));
} else {
listener.onError(false, context.getResources().getString(R.string.fail_loadMore));
}
}
public void handleFailure(){
listener.onError(true, context.getResources().getString(R.string.fail_load));
}
}