content: package im.actor.sdk.controllers.group.view;
  
  import android.app.Activity;
  import android.app.AlertDialog;
  import android.content.Context;
  import android.view.View;
  import android.view.ViewGroup;
  import android.widget.TextView;
  import android.widget.Toast;
  
  import com.google.i18n.phonenumbers.NumberParseException;
  import com.google.i18n.phonenumbers.PhoneNumberUtil;
  import com.google.i18n.phonenumbers.Phonenumber;
  
  import java.util.ArrayList;
  import java.util.Arrays;
  import java.util.Collection;
  import java.util.Optional;
  
  import im.actor.core.viewmodel.CommandCallback;
  import im.actor.core.viewmodel.GroupVM;
  import im.actor.core.viewmodel.UserPhone;
  import im.actor.runtime.actors.messages.*;
  import im.actor.runtime.actors.messages.Void;
  import im.actor.sdk.ActorSDK;
  import im.actor.sdk.ActorSDKLauncher;
  import im.actor.sdk.R;
  import im.actor.sdk.controllers.ActorBinder;
  import im.actor.sdk.controllers.Intents;
  import im.actor.sdk.controllers.activity.BaseActivity;
  import im.actor.sdk.util.AlertListBuilder;
  import im.actor.sdk.util.Screen;
  import im.actor.sdk.view.avatar.AvatarView;
  import im.actor.sdk.view.adapters.HolderAdapter;
  import im.actor.sdk.view.adapters.ViewHolder;
  import im.actor.core.entity.GroupMember;
  import im.actor.core.viewmodel.UserVM;
  
  import static im.actor.sdk.util.ActorSDKMessenger.messenger;
  import static im.actor.sdk.util.ActorSDKMessenger.users;
  
  public class MembersAdapter extends HolderAdapter<GroupMember> {
  
      public static final int LOAD_GAP = 10;
      private static final int LIMIT = 20;
      private ArrayList<GroupMember> members = new ArrayList<GroupMember>();
      private ActorBinder BINDER = new ActorBinder();
      private boolean loadInProgress = false;
      private boolean loaddedToEnd = false;
      private LoadedCallback callback;
  
      public MembersAdapter(Context context, int groupId) {
          super(context);
          this.groupId = groupId;
      }
  
      public void setMembers(Collection<GroupMember> members) {
          setMembers(members, true, true);
      }
  
      public void setMembers(Collection<GroupMember> members, boolean clear, boolean sort) {
          if (clear) {
              this.members.clear();
          }
          if (sort) {
              GroupMember[] membersArray = members.toArray(new GroupMember[members.size()]);
              Arrays.sort(membersArray, (a, b) -> {
                  if (a.isAdministrator() && !b.isAdministrator()) {
                      return -1;
                  }
                  if (b.isAdministrator() && !a.isAdministrator()) {
                      return 1;
                  }
                  String an = users().get(a.getUid()).getName().get();
                  String bn = users().get(b.getUid()).getName().get();
                  return an.compareTo(bn);
              });
              this.members.addAll(Arrays.asList(membersArray));
          } else {
              this.members.addAll(members);
          }
          notifyDataSetChanged();
      }
  
      @Override
      protected void onBindViewHolder(ViewHolder<GroupMember> holder, GroupMember obj, int position, Context context) {
          super.onBindViewHolder(holder, obj, position, context);
          if (position >= getCount() - LOAD_GAP) {
              loadMore();
          }
  
      }
  
      private int groupId;
      private boolean isInitiallyLoaded;
      private byte[] nextMembers;
      private ArrayList<Integer> rawMembers = new ArrayList<>();
  
      public void initLoad(LoadedCallback callback) {
          this.callback = callback;
          if (!isInitiallyLoaded) {
              loadMore();
          }
      }
  
      public interface LoadedCallback {
          void onLoaded();
  
          void onLoadedToEnd();
      }
  
      private void loadMore() {
          if (!loadInProgress && !loaddedToEnd) {
              loadInProgress = true;
              messenger().loadMembers(groupId, LIMIT, nextMembers).then(groupMembersSlice -> {
                  if (!isInitiallyLoaded) {
                      isInitiallyLoaded = true;
                      if (callback != null) {
                          callback.onLoaded();
                      }
                  }
                  nextMembers = groupMembersSlice.getNext();
                  loaddedToEnd = nextMembers == null;
                  if (loaddedToEnd && callback != null) {
                      callback.onLoadedToEnd();
                  }
                  loadInProgress = false;
                  setMembers(groupMembersSlice.getMembers(), false, false);
              });
          }
      }
  
      @Override
      public int getCount() {
          return members.size();
      }
  
      @Override
      public GroupMember getItem(int position) {
          return members.get(position);
      }
  
      @Override
      public long getItemId(int position) {
          return members.get(position).getUid();
      }
  
      @Override
      protected ViewHolder<GroupMember> createHolder(GroupMember obj) {
          return new GroupViewHolder();
      }
  
      private class GroupViewHolder extends ViewHolder<GroupMember> {
  
          private TextView userName;
          private View admin;
          private AvatarView avatarView;
          private TextView online;
          private ActorBinder.Binding onlineBinding;
          private UserVM user;
  
          @Override
          public View init(GroupMember data, ViewGroup viewGroup, Context context) {
              View res = ((Activity) context).getLayoutInflater().inflate(R.layout.fragment_group_item, viewGroup, false);
              userName = (TextView) res.findViewById(R.id.name);
              avatarView = (AvatarView) res.findViewById(R.id.avatar);
              avatarView.init(Screen.dp(42), 18);
              admin = res.findViewById(R.id.adminFlag);
              online = (TextView) res.findViewById(R.id.online);
              ((TextView) admin).setTextColor(ActorSDK.sharedActor().style.getGroupAdminColor());
              ((TextView) res.findViewById(R.id.name)).setTextColor(ActorSDK.sharedActor().style.getTextPrimaryColor());
              // res.findViewById(R.id.divider).setBackgroundColor(ActorSDK.sharedActor().style.getDividerColor());
              return res;
          }
  
          @Override
          public void bind(GroupMember data, int position, Context context) {
              boolean needRebind = user == null || data.getUid() != user.getId();
              user = users().get(data.getUid());
              ActorSDK.sharedActor().getMessenger().onUserVisible(data.getUid());
              onlineBinding = BINDER.bindOnline(online, user);
  
              if (needRebind) {
                  avatarView.bind(user);
              }
  
              userName.setText(user.getName().get());
  
              if (data.isAdministrator()) {
                  admin.setVisibility(View.VISIBLE);
              } else {
                  admin.setVisibility(View.GONE);
              }
          }
  
          @Override
          public void unbind(boolean full) {
              if (full) {
                  avatarView.unbind();
              }
              if (onlineBinding != null) {
                  BINDER.unbind(onlineBinding);
              }
          }
  
      }
  
      @Override
      public void dispose() {
          super.dispose();
          BINDER.unbindAll();
      }
  
      public void onMemberClick(GroupVM groupVM, UserVM userVM, boolean isAdministrator, boolean isInvitedByMe, BaseActivity activity) {
          AlertListBuilder alertListBuilder = new AlertListBuilder();
          final ArrayList<UserPhone> phones = userVM.getPhones().get();
          alertListBuilder.addItem(activity.getString(R.string.group_context_message).replace("{0}", userVM.getName().get()), () -> activity.startActivity(Intents.openPrivateDialog(userVM.getId(), true, activity)));
          if (phones.size() != 0) {
              alertListBuilder.addItem(activity.getString(R.string.group_context_call).replace("{0}", userVM.getName().get()), () -> {
                  if (phones.size() == 1) {
                      activity.startActivity(Intents.call(phones.get(0).getPhone()));
                  } else {
                      CharSequence[] sequences = new CharSequence[phones.size()];
                      for (int i = 0; i < sequences.length; i++) {
                          try {
                              Phonenumber.PhoneNumber number = PhoneNumberUtil.getInstance().parse("+" + phones.get(i).getPhone(), "us");
                              sequences[i] = phones.get(i).getTitle() + ": " + PhoneNumberUtil.getInstance().format(number, PhoneNumberUtil.PhoneNumberFormat.INTERNATIONAL);
                          } catch (NumberParseException e) {
                              e.printStackTrace();
                              sequences[i] = phones.get(i).getTitle() + ": +" + phones.get(i).getPhone();
                          }
                      }
                      new AlertDialog.Builder(activity)
                              .setItems(sequences, (dialog1, which1) -> {
                                  activity.startActivity(Intents.call(phones.get(which1).getPhone()));
                              })
                              .show()
                              .setCanceledOnTouchOutside(true);
                  }
              });
          }
          alertListBuilder.addItem(activity.getString(R.string.group_context_view).replace("{0}", userVM.getName().get()), () -> ActorSDKLauncher.startProfileActivity(activity, userVM.getId()));
          if (groupVM.getIsCanKickAnyone().get() || (groupVM.getIsCanKickInvited().get() && isInvitedByMe)) {
              alertListBuilder.addItem(activity.getString(R.string.group_context_remove).replace("{0}", userVM.getName().get()), () -> {
                  new AlertDialog.Builder(activity)
                          .setMessage(activity.getString(R.string.alert_group_remove_text).replace("{0}", userVM.getName().get()))
                          .setPositiveButton(R.string.alert_group_remove_yes, (dialog2, which1) -> {
                              activity.execute(messenger().kickMember(groupVM.getId(), userVM.getId()),
                                      R.string.progress_common, new CommandCallback<Void>() {
                                          @Override
                                          public void onResult(Void res1) {
  
                                          }
  
                                          @Override
                                          public void onError(Exception e) {
                                              Toast.makeText(activity, R.string.toast_unable_kick, Toast.LENGTH_SHORT).show();
                                          }
                                      });
                          })
                          .setNegativeButton(R.string.dialog_cancel, null)
                          .show()
                          .setCanceledOnTouchOutside(true);
              });
          }
          if (groupVM.getIsCanEditAdmins().get() && !userVM.isBot()) {
              alertListBuilder.addItem(!isAdministrator ? activity.getResources().getString(R.string.group_make_admin) : activity.getResources().getString(R.string.group_revoke_admin), () -> {
                  if (!isAdministrator) {
                      messenger().makeAdmin(groupVM.getId(), userVM.getId()).start(new CommandCallback<Void>() {
                          @Override
                          public void onResult(Void res) {
  
                          }
  
                          @Override
                          public void onError(Exception e) {
  
                          }
                      });
                  } else {
                      messenger().revokeAdmin(groupVM.getId(), userVM.getId()).start(new CommandCallback<Void>() {
                          @Override
                          public void onResult(Void res) {
  
                          }
  
                          @Override
                          public void onError(Exception e) {
  
                          }
                      });
                  }
              });
          }
          alertListBuilder.build(activity)
                  .show()
                  .setCanceledOnTouchOutside(true);
      }
  }
  