package tellh.com.gitclub.model.net.DataSource;
import android.text.TextUtils;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import okhttp3.ResponseBody;
import retrofit2.Response;
import rx.Observable;
import rx.functions.Func1;
import tellh.com.gitclub.common.config.Constant.SortType.SortType_Repo;
import tellh.com.gitclub.common.utils.RxJavaUtils;
import tellh.com.gitclub.common.utils.StringUtils;
import tellh.com.gitclub.model.entity.Branch;
import tellh.com.gitclub.model.entity.Dir;
import tellh.com.gitclub.model.entity.File;
import tellh.com.gitclub.model.entity.GitTree;
import tellh.com.gitclub.model.entity.ReadMe;
import tellh.com.gitclub.model.entity.RepositoryInfo;
import tellh.com.gitclub.model.entity.SearchResult;
import tellh.com.gitclub.model.entity.UserEntity;
import tellh.com.gitclub.model.net.service.RepositoryService;
import tellh.com.recyclertreeview_lib.LayoutItemType;
import tellh.com.recyclertreeview_lib.TreeNode;
import static tellh.com.gitclub.common.config.Constant.PER_PAGE;
/**
* Created by tlh on 2016/8/27 :)
*/
public class RepositoryDataSource {
private RepositoryService repositoryApi;
public RepositoryDataSource(RepositoryService repositoryApi) {
this.repositoryApi = repositoryApi;
}
public Observable<RepositoryInfo> getRepoInfo(String owner, String repo) {
return repositoryApi.getRepoInfo(owner, repo)
.compose(RxJavaUtils.<RepositoryInfo>applySchedulers());
}
public Observable<List<RepositoryInfo>> listForks(String owner, String repo, int page) {
return repositoryApi.listForks(owner, repo, page)
.compose(RxJavaUtils.<List<RepositoryInfo>>applySchedulers());
}
public Observable<List<UserEntity>> listWatchers(String owner, String repo, int page) {
return repositoryApi.listWatchers(owner, repo, page)
.compose(RxJavaUtils.<List<UserEntity>>applySchedulers());
}
public Observable<List<UserEntity>> listStargazers(String owner, String repo, int page) {
return repositoryApi.listStargazers(owner, repo, page)
.compose(RxJavaUtils.<List<UserEntity>>applySchedulers());
}
public Observable<List<UserEntity>> listContributors(String owner, String repo, int page) {
return repositoryApi.listContributors(owner, repo, page)
.compose(RxJavaUtils.<List<UserEntity>>applySchedulers());
}
public Observable<RepositoryInfo> toFork(String owner, String repo) {
return repositoryApi.toFork(owner, repo)
.compose(RxJavaUtils.<RepositoryInfo>applySchedulers());
}
public Observable<Boolean> toStar(String owner, String repo) {
return repositoryApi.toStar(owner, repo)
.compose(RxJavaUtils.<Response<ResponseBody>>applySchedulers())
.compose(RxJavaUtils.checkIfSuccessCode());
}
public Observable<Boolean> toWatch(String owner, String repo) {
return repositoryApi.toWatch(owner, repo)
.compose(RxJavaUtils.<Response<ResponseBody>>applySchedulers())
.compose(RxJavaUtils.checkIfSuccessCode());
}
public Observable<Boolean> unStar(String owner, String repo) {
return repositoryApi.unStar(owner, repo)
.compose(RxJavaUtils.<Response<ResponseBody>>applySchedulers())
.compose(RxJavaUtils.checkIfSuccessCode());
}
public Observable<Boolean> unWatch(String owner, String repo) {
return repositoryApi.unWatch(owner, repo)
.compose(RxJavaUtils.<Response<ResponseBody>>applySchedulers())
.compose(RxJavaUtils.checkIfSuccessCode());
}
public Observable<Boolean> checkStarred(String owner, String repo) {
return repositoryApi.checkStarred(owner, repo)
.compose(RxJavaUtils.<Response<ResponseBody>>applySchedulers())
.compose(RxJavaUtils.checkIfSuccessCode());
}
public Observable<Boolean> checkWatching(String owner, String repo) {
return repositoryApi.checkWatching(owner, repo)
.compose(RxJavaUtils.<Response<ResponseBody>>applySchedulers())
.compose(RxJavaUtils.checkIfSuccessCode());
}
public Observable<Boolean> delete(String owner, String repo) {
return repositoryApi.delete(owner, repo)
.compose(RxJavaUtils.<Response<ResponseBody>>applySchedulers())
.compose(RxJavaUtils.checkIfSuccessCode());
}
public Observable<List<Branch>> listBranches(String owner, String repo) {
return repositoryApi.listBranches(owner, repo)
.compose(RxJavaUtils.<List<Branch>>applySchedulers());
}
public Observable<List<TreeNode>> getContent(final String owner, final String repo, final Branch branch) {
return repositoryApi.getContent(owner, repo, branch.getCommit().getSha())
.map(new Func1<GitTree, List<TreeNode>>() {
@Override
public List<TreeNode> call(GitTree gitTree) {
List<GitTree.TreeEntity> treeEntities = gitTree.getTree();
List<TreeNode> treeViewNodes = new ArrayList<>(treeEntities.size());
for (int index = 0; index < treeEntities.size(); ) {
GitTree.TreeEntity treeEntity = treeEntities.get(index++);
switch (treeEntity.getNodeType()) {
case GitTree.DIR:
TreeNode<Dir> dirTreeNode = new TreeNode<>(new Dir(treeEntity.getPath(), treeEntity.getPath()));
index = findChildNode(treeEntities, index, dirTreeNode, treeEntity.getPath(), owner, repo, branch.getName());
treeViewNodes.add(dirTreeNode);
break;
case GitTree.FILE:
treeViewNodes.add(new TreeNode<>(new File(treeEntity.getPath(),
treeEntity.getHtml_url(owner, repo, branch.getName()))));
break;
}
}
sortNodeList(treeViewNodes);
return treeViewNodes;
}
}).compose(RxJavaUtils.<List<TreeNode>>applySchedulers());
}
private int findChildNode(List<GitTree.TreeEntity> treeEntities, int index, TreeNode<Dir> dirNode,
String dirPath, final String owner, final String repo, String branchName) {
while (index < treeEntities.size()
&& treeEntities.get(index).getPath().startsWith(dirPath + "/")) {
GitTree.TreeEntity childEntity = treeEntities.get(index++);
String childPath = childEntity.getPath();
String nodeName = childPath.substring(childPath.lastIndexOf("/") + 1, childPath.length());
switch (childEntity.getNodeType()) {
case GitTree.DIR:
TreeNode<Dir> dirChildNode = new TreeNode<>(new Dir(nodeName, childPath));
index = findChildNode(treeEntities, index, dirChildNode, childEntity.getPath(), owner, repo, branchName);
dirNode.addChild(dirChildNode);
break;
case GitTree.FILE:
dirNode.addChild(new TreeNode<>(new File(nodeName, childEntity.getHtml_url(owner, repo, branchName))));
break;
}
}
// Compress the tree high and sort the child node list.
List<TreeNode> childList = dirNode.getChildList();
TreeNode firstChild = childList.get(0);
LayoutItemType firstChildContent = firstChild.getContent();
if (childList.size() == 1 && firstChildContent instanceof Dir) {
Dir childDirNode = (Dir) firstChildContent;
dirNode.getContent().dirName = StringUtils.append(dirNode.getContent().dirName, "/", childDirNode.dirName);
childList.clear();
List<TreeNode> firstChildChildList = firstChild.getChildList();
for (TreeNode treeNode : firstChildChildList) {
treeNode.setParent(dirNode);
}
childList.addAll(firstChildChildList);
} else {
//push Dir node to the front and pull File node to the back.
sortNodeList(childList);
}
return index;
}
private void sortNodeList(List<TreeNode> nodeList) {
int front = 0;
int back = nodeList.size() - 1;
while (true) {
while (front < back && nodeList.get(front).getContent() instanceof Dir)
front++;
while (front < back && nodeList.get(back).getContent() instanceof File)
back--;
if (front < back)
Collections.swap(nodeList, front, back);
else break;
}
}
public Observable<SearchResult<RepositoryInfo>> search(String keyWord, String language, int page) {
return search(keyWord, language, null, page)
.compose(RxJavaUtils.<SearchResult<RepositoryInfo>>applySchedulers());
}
public Observable<SearchResult<RepositoryInfo>> search(String keyWord, String language, SortType_Repo sort, int page) {
if (keyWord == null)
keyWord = "";
// if (location != null && !location.isEmpty()) {
// q += "+location:" + location;
// }
if (!TextUtils.isEmpty(language))
keyWord += language;
if (TextUtils.isEmpty(sort.val()))
return repositoryApi.search(keyWord, page, PER_PAGE)
.compose(RxJavaUtils.<SearchResult<RepositoryInfo>>applySchedulers());
return repositoryApi.search(keyWord, sort.val(), page, PER_PAGE)
.compose(RxJavaUtils.<SearchResult<RepositoryInfo>>applySchedulers());
}
public Observable<ReadMe> getReadMe(String owner, String repo) {
return repositoryApi.getReadMe(owner, repo)
.compose(RxJavaUtils.<ReadMe>applySchedulers());
}
}