package chat.rocket.persistence.realm.repositories;

import android.os.Looper;
import android.support.v4.util.Pair;
import com.hadisatrio.optional.Optional;
import io.reactivex.Flowable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.realm.Case;
import io.realm.RealmResults;
import io.realm.Sort;

import java.util.ArrayList;
import java.util.List;
import chat.rocket.core.SortDirection;
import chat.rocket.core.models.User;
import chat.rocket.core.repositories.UserRepository;
import chat.rocket.persistence.realm.RealmStore;
import chat.rocket.persistence.realm.models.ddp.RealmUser;
import hu.akarnokd.rxjava.interop.RxJavaInterop;

public class RealmUserRepository extends RealmRepository implements UserRepository {

  private final String hostname;

  public RealmUserRepository(String hostname) {
    this.hostname = hostname;
  }

  @Override
  public Flowable<Optional<User>> getCurrent() {
    return Flowable.defer(() -> Flowable.using(
        () -> new Pair<>(RealmStore.getRealm(hostname), Looper.myLooper()),
        pair -> RxJavaInterop.toV2Flowable(
            pair.first.where(RealmUser.class)
                .isNotEmpty(RealmUser.EMAILS)
                .findAll()
                .<RealmResults<RealmUser>>asObservable()),
        pair -> close(pair.first, pair.second)
    )
        .unsubscribeOn(AndroidSchedulers.from(Looper.myLooper()))
        .filter(it -> it != null && it.isLoaded()
            && it.isValid())
        .map(realmUsers -> {
          if (realmUsers.size() > 0) {
            return Optional.of(realmUsers.get(0).asUser());
          }

          return Optional.<User>absent();
        }));
  }

  @Override
  public Flowable<List<User>> getSortedLikeName(String name, SortDirection direction, int limit) {
    return Flowable.defer(() -> Flowable.using(
        () -> new Pair<>(RealmStore.getRealm(hostname), Looper.myLooper()),
        pair -> RxJavaInterop.toV2Flowable(
            pair.first.where(RealmUser.class)
                .like(RealmUser.USERNAME, "*" + name + "*", Case.INSENSITIVE)
                .findAllSorted(RealmUser.USERNAME,
                    direction.equals(SortDirection.ASC) ? Sort.ASCENDING : Sort.DESCENDING)
                .asObservable()),
        pair -> close(pair.first, pair.second)
    )
        .unsubscribeOn(AndroidSchedulers.from(Looper.myLooper()))
        .filter(realmUsers -> realmUsers != null && realmUsers.isLoaded()
            && realmUsers.isValid())
        .map(realmUsers -> toList(safeSubList(realmUsers, 0, limit))));
  }

  private List<User> toList(RealmResults<RealmUser> realmUsers) {
    int total = realmUsers.size();

    final List<User> userList = new ArrayList<>(total);

    for (int i = 0; i < total; i++) {
      userList.add(realmUsers.get(i).asUser());
    }

    return userList;
  }

  private List<User> toList(List<RealmUser> realmUsers) {
    int total = realmUsers.size();

    final List<User> userList = new ArrayList<>(total);

    for (int i = 0; i < total; i++) {
      userList.add(realmUsers.get(i).asUser());
    }

    return userList;
  }
}

@@ -736,17 +736,16 @@
 itory %7B%0A
-%0A
   privat
@@ -1689,20 +1689,24 @@
 lowable%3C
-List
+Optional
 %3CUser%3E%3E 
@@ -1708,16 +1708,1034 @@
 er%3E%3E get
+ByUsername(String username) %7B%0A    return Flowable.defer(() -%3E Flowable.using(%0A        () -%3E new Pair%3C%3E(RealmStore.getRealm(hostname), Looper.myLooper()),%0A        pair -%3E %7B%0A          RealmUser realmUser = pair.first.where(RealmUser.class)%0A              .equalTo(RealmUser.USERNAME, username)%0A              .findFirst();%0A%0A          if (realmUser == null) %7B%0A            return Flowable.just(Optional.%3CRealmUser%3Eabsent());%0A          %7D%0A%0A          return RxJavaInterop.toV2Flowable(%0A              realmUser%0A                  .%3CRealmUser%3EasObservable()%0A                  .filter(user -%3E user.isLoaded() && user.isValid())%0A                  .map(Optional::of));%0A        %7D,%0A        pair -%3E close(pair.first, pair.second)%0A    )%0A        .unsubscribeOn(AndroidSchedulers.from(Looper.myLooper()))%0A        .map(optional -%3E %7B%0A          if (optional.isPresent()) %7B%0A            return Optional.of(optional.get().asUser());%0A          %7D%0A%0A          return Optional.absent();%0A        %7D));%0A  %7D%0A%0A  @Override%0A  public Flowable%3CList%3CUser%3E%3E get
 SortedLi
@@ -2756,33 +2756,8 @@
 name
-, SortDirection direction
 , in
@@ -3113,83 +3113,8 @@
 AME,
-%0A                    direction.equals(SortDirection.ASC) ? Sort.ASCENDING :
  Sor
@@ -3472,286 +3472,8 @@
  %7D%0A%0A
-  private List%3CUser%3E toList(RealmResults%3CRealmUser%3E realmUsers) %7B%0A    int total = realmUsers.size();%0A%0A    final List%3CUser%3E userList = new ArrayList%3C%3E(total);%0A%0A    for (int i = 0; i %3C total; i++) %7B%0A      userList.add(realmUsers.get(i).asUser());%0A    %7D%0A%0A    return userList;%0A  %7D%0A%0A
   pr
@@ -3737,10 +3737,9 @@
 st;%0A  %7D%0A
+
 %7D
-%0A

Update RealmUserRepository.java