package org.thoughtcrime.securesms;

import android.content.Context;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.RecyclerView;
import chat.delta.rpc.Rpc;
import chat.delta.rpc.RpcException;
import com.b44t.messenger.DcChat;
import com.b44t.messenger.DcChatlist;
import com.b44t.messenger.DcContact;
import com.b44t.messenger.DcContext;
import com.b44t.messenger.DcLot;
import com.b44t.messenger.DcMsg;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.contacts.ContactSelectionListItem;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.util.Util;

public class ProfileAdapter extends RecyclerView.Adapter {
  private static final String TAG = "ProfileAdapter";

  public static final int ITEM_AVATAR = 10;
  public static final int ITEM_DIVIDER = 20;
  public static final int ITEM_SIGNATURE = 25;
  public static final int ITEM_ALL_MEDIA_BUTTON = 30;
  public static final int ITEM_SEND_MESSAGE_BUTTON = 35;
  public static final int ITEM_LAST_SEEN = 40;
  public static final int ITEM_BLOCKED = 43;
  public static final int ITEM_INTRODUCED_BY = 45;
  public static final int ITEM_HEADER = 53;
  public static final int ITEM_MEMBERS = 55;
  public static final int ITEM_SHARED_CHATS = 60;

  private final @NonNull Context context;
  private final @NonNull Fragment fragment;
  private final @NonNull DcContext dcContext;
  private @Nullable DcChat dcChat;
  private @Nullable DcContact dcContact;

  private final @NonNull ArrayList<ItemData> itemData = new ArrayList<>();
  private DcChatlist itemDataSharedChats;
  private String itemDataStatusText;
  private boolean isOutBroadcast;
  private int[] memberList;
  private final Set<Integer> selectedMembers;

  private final LayoutInflater layoutInflater;
  private final ItemClickListener clickListener;
  private final GlideRequests glideRequests;

  static class ItemData {
    final int viewType;
    final int contactId;
    final int chatlistIndex;
    final String label;
    final int icon;

    ItemData(int viewType, String label, int icon) {
      this(viewType, 0, 0, label, icon);
    }

    ItemData(int viewType, int contactId, int chatlistIndex) {
      this(viewType, contactId, chatlistIndex, null, 0);
    }

    private ItemData(
        int viewType, int contactId, int chatlistIndex, @Nullable String label, int icon) {
      this.viewType = viewType;
      this.contactId = contactId;
      this.chatlistIndex = chatlistIndex;
      this.label = label;
      this.icon = icon;
    }
  }
  ;

  public ProfileAdapter(
      @NonNull Fragment fragment,
      @NonNull GlideRequests glideRequests,
      @Nullable ItemClickListener clickListener) {
    super();
    this.fragment = fragment;
    this.context = fragment.requireContext();
    this.glideRequests = glideRequests;
    this.clickListener = clickListener;
    this.dcContext = DcHelper.getContext(context);
    this.layoutInflater = LayoutInflater.from(context);
    this.selectedMembers = new HashSet<>();
  }

  @Override
  public int getItemCount() {
    return itemData.size();
  }

  @Override
  public int getItemViewType(int i) {
    return itemData.get(i).viewType;
  }

  public static class ViewHolder extends RecyclerView.ViewHolder {
    public ViewHolder(View itemView) {
      super(itemView);
    }
  }

  @NonNull
  @Override
  public ProfileAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
    if (viewType == ITEM_HEADER) {
      final View item =
          LayoutInflater.from(context)
              .inflate(R.layout.contact_selection_list_divider, parent, false);
      return new ViewHolder(item);
    } else if (viewType == ITEM_DIVIDER) {
      final View item =
          LayoutInflater.from(context).inflate(R.layout.profile_divider, parent, false);
      return new ViewHolder(item);
    } else if (viewType == ITEM_MEMBERS) {
      final ContactSelectionListItem item =
          (ContactSelectionListItem)
              layoutInflater.inflate(R.layout.contact_selection_list_item, parent, false);
      return new ViewHolder(item);
    } else if (viewType == ITEM_SHARED_CHATS) {
      final ConversationListItem item =
          (ConversationListItem)
              layoutInflater.inflate(R.layout.conversation_list_item_view, parent, false);
      item.hideItemDivider();
      return new ViewHolder(item);
    } else if (viewType == ITEM_SIGNATURE) {
      final ProfileStatusItem item =
          (ProfileStatusItem) layoutInflater.inflate(R.layout.profile_status_item, parent, false);
      return new ViewHolder(item);
    } else if (viewType == ITEM_AVATAR) {
      final ProfileAvatarItem item =
          (ProfileAvatarItem) layoutInflater.inflate(R.layout.profile_avatar_item, parent, false);
      return new ViewHolder(item);
    } else if (viewType == ITEM_ALL_MEDIA_BUTTON || viewType == ITEM_SEND_MESSAGE_BUTTON) {
      final ProfileTextItem item =
          (ProfileTextItem)
              layoutInflater.inflate(R.layout.profile_text_item_button, parent, false);
      return new ViewHolder(item);
    } else if (viewType == ITEM_LAST_SEEN
        || viewType == ITEM_INTRODUCED_BY
        || viewType == ITEM_BLOCKED) {
      final ProfileTextItem item =
          (ProfileTextItem) layoutInflater.inflate(R.layout.profile_text_item_small, parent, false);
      return new ViewHolder(item);
    } else {
      final ProfileTextItem item =
          (ProfileTextItem) layoutInflater.inflate(R.layout.profile_text_item, parent, false);
      return new ViewHolder(item);
    }
  }

  @Override
  public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
    ViewHolder holder = (ViewHolder) viewHolder;
    ItemData data = itemData.get(i);
    if (holder.itemView instanceof ContactSelectionListItem) {
      ContactSelectionListItem contactItem = (ContactSelectionListItem) holder.itemView;

      int contactId = data.contactId;
      DcContact dcContact = null;
      String label = null;
      String name;
      String addr = null;

      if (contactId == DcContact.DC_CONTACT_ID_ADD_MEMBER) {
        name = context.getString(R.string.group_add_members);
      } else if (contactId == DcContact.DC_CONTACT_ID_QR_INVITE) {
        name = context.getString(R.string.qrshow_title);
      } else {
        dcContact = dcContext.getContact(contactId);
        name = dcContact.getDisplayName();
        addr = dcContact.getAddr();
      }

      contactItem.unbind(glideRequests);
      contactItem.set(glideRequests, contactId, dcContact, name, addr, label, false, true);
      contactItem.setSelected(selectedMembers.contains(contactId));
      contactItem.setOnClickListener(view -> clickListener.onMemberClicked(contactId));
      contactItem.setOnLongClickListener(
          view -> {
            clickListener.onMemberLongClicked(contactId);
            return true;
          });
    } else if (holder.itemView instanceof ConversationListItem) {
      ConversationListItem conversationListItem = (ConversationListItem) holder.itemView;
      int chatlistIndex = data.chatlistIndex;

      int chatId = itemDataSharedChats.getChatId(chatlistIndex);
      DcChat chat = dcContext.getChat(chatId);
      DcLot summary = itemDataSharedChats.getSummary(chatlistIndex, chat);

      conversationListItem.bind(
          DcHelper.getThreadRecord(context, summary, chat),
          itemDataSharedChats.getMsgId(chatlistIndex),
          summary,
          glideRequests,
          Collections.emptySet(),
          false);
      conversationListItem.setOnClickListener(view -> clickListener.onSharedChatClicked(chatId));
    } else if (holder.itemView instanceof ProfileStatusItem) {
      ProfileStatusItem item = (ProfileStatusItem) holder.itemView;
      item.setOnLongClickListener(
          view -> {
            clickListener.onStatusLongClicked(dcContact == null);
            return true;
          });
      item.set(data.label);
    } else if (holder.itemView instanceof ProfileAvatarItem) {
      ProfileAvatarItem item = (ProfileAvatarItem) holder.itemView;
      item.setAvatarClickListener(view -> clickListener.onAvatarClicked());
      item.set(glideRequests, dcChat, dcContact, memberList);
    } else if (holder.itemView instanceof ProfileTextItem) {
      ProfileTextItem item = (ProfileTextItem) holder.itemView;
      item.setOnClickListener(view -> clickListener.onSettingsClicked(data.viewType));
      boolean tintIcon = data.viewType != ITEM_INTRODUCED_BY && data.viewType != ITEM_BLOCKED;
      item.set(data.label, data.icon, tintIcon);
      if (data.viewType == ITEM_BLOCKED) {
        int padding =
            (int)
                ((float)
                        context
                            .getResources()
                            .getDimensionPixelSize(R.dimen.contact_list_normal_padding)
                    * 1.2);
        item.setPadding(
            item.getPaddingLeft(), item.getPaddingTop(), item.getPaddingRight(), padding);
      } else if (data.viewType == ITEM_INTRODUCED_BY) {
        int padding =
            context.getResources().getDimensionPixelSize(R.dimen.contact_list_normal_padding);
        item.setPadding(
            item.getPaddingLeft(), padding, item.getPaddingRight(), item.getPaddingBottom());
      } else if (data.viewType == ITEM_ALL_MEDIA_BUTTON && dcChat != null) {
        Util.runOnAnyBackgroundThread(
            () -> {
              String c = getAllMediaCountString(dcChat.getId());
              Util.runOnMain(
                  () -> {
                    item.setValue(c);
                  });
            });
      }
    } else if (data.viewType == ITEM_HEADER) {
      TextView textView = holder.itemView.findViewById(R.id.label);
      textView.setText(data.label);
    }
  }

  public interface ItemClickListener {
    void onSettingsClicked(int settingsId);

    void onStatusLongClicked(boolean isMultiUser);

    void onSharedChatClicked(int chatId);

    void onMemberClicked(int contactId);

    void onMemberLongClicked(int contactId);

    void onAvatarClicked();
  }

  public void toggleMemberSelection(int contactId) {
    if (!selectedMembers.remove(contactId)) {
      selectedMembers.add(contactId);
    }
    notifyDataSetChanged();
  }

  @NonNull
  public Collection<Integer> getSelectedMembers() {
    return new HashSet<>(selectedMembers);
  }

  public int getSelectedMembersCount() {
    return selectedMembers.size();
  }

  @NonNull
  public String getStatusText() {
    return itemDataStatusText;
  }

  public void clearSelection() {
    selectedMembers.clear();
    notifyDataSetChanged();
  }

  public void changeData(
      @Nullable int[] memberList,
      @Nullable DcContact dcContact,
      @Nullable DcChatlist sharedChats,
      @Nullable DcChat dcChat) {
    this.dcChat = dcChat;
    this.dcContact = dcContact;
    itemData.clear();
    itemDataSharedChats = sharedChats;
    itemDataStatusText = "";
    isOutBroadcast = dcChat != null && dcChat.isOutBroadcast();
    boolean isMailingList = dcChat != null && dcChat.isMailingList();
    boolean isInBroadcast = dcChat != null && dcChat.isInBroadcast();
    boolean isSelfTalk = dcChat != null && dcChat.isSelfTalk();
    boolean isDeviceTalk = dcChat != null && dcChat.isDeviceTalk();
    this.memberList = memberList;

    itemData.add(new ItemData(ITEM_AVATAR, null, 0));

    if (isSelfTalk) {
      itemDataStatusText = context.getString(R.string.saved_messages_explain);
    } else if (dcContact != null) {
      itemDataStatusText = dcContact.getStatus();
    } else if (dcChat != null && dcChat.isEncrypted()) {
      // Load group or channel description
      try {
        Rpc rpc = DcHelper.getRpc(context);
        itemDataStatusText = rpc.getChatDescription(rpc.getSelectedAccountId(), dcChat.getId());
      } catch (RpcException e) {
        Log.e(TAG, "RPC error", e);
      }
    }

    if (!itemDataStatusText.isEmpty()) {
      itemData.add(new ItemData(ITEM_SIGNATURE, itemDataStatusText, 0));
    } else {
      itemData.add(new ItemData(ITEM_DIVIDER, null, 0));
    }

    itemData.add(
        new ItemData(
            ITEM_ALL_MEDIA_BUTTON,
            context.getString(R.string.apps_and_media),
            R.drawable.ic_apps_24));

    if (dcContact != null && !isDeviceTalk && !isSelfTalk) {
      itemData.add(
          new ItemData(
              ITEM_SEND_MESSAGE_BUTTON,
              context.getString(R.string.send_message),
              R.drawable.ic_send_sms_white_24dp));
    }

    /*
    if (dcContact != null && !isDeviceTalk && !isSelfTalk) {
      long lastSeenTimestamp = dcContact.getLastSeen();
      String lastSeenTxt;
      if (lastSeenTimestamp == 0) {
        lastSeenTxt = context.getString(R.string.last_seen_unknown);
      } else {
        lastSeenTxt =
            context.getString(
                R.string.last_seen_at,
                DateUtils.getExtendedTimeSpanString(context, lastSeenTimestamp));
      }
      itemData.add(new ItemData(ITEM_LAST_SEEN, lastSeenTxt, 0));
    }
    */

    if (dcContact != null && !isDeviceTalk && !isSelfTalk && dcContact.isBlocked()) {
      itemData.add(
          new ItemData(
              ITEM_BLOCKED,
              context.getString(R.string.contact_blocked),
              R.drawable.contact_blocked_24));
    }

    if (memberList != null && !isInBroadcast && !isMailingList) {
      itemData.add(new ItemData(ITEM_DIVIDER, null, 0));
      if (dcChat != null) {
        if (dcChat.canSend() && dcChat.isEncrypted()) {
          if (!isOutBroadcast) {
            itemData.add(new ItemData(ITEM_MEMBERS, DcContact.DC_CONTACT_ID_ADD_MEMBER, 0));
          }
          itemData.add(new ItemData(ITEM_MEMBERS, DcContact.DC_CONTACT_ID_QR_INVITE, 0));
        }
      }
      for (int value : memberList) {
        itemData.add(new ItemData(ITEM_MEMBERS, value, 0));
      }
    }

    if (!isDeviceTalk && sharedChats != null && sharedChats.getCnt() > 0) {
      itemData.add(new ItemData(ITEM_HEADER, context.getString(R.string.profile_shared_chats), 0));
      for (int i = 0; i < sharedChats.getCnt(); i++) {
        itemData.add(new ItemData(ITEM_SHARED_CHATS, 0, i));
      }
    }

    if (dcContact != null && !isDeviceTalk && !isSelfTalk) {
      itemData.add(new ItemData(ITEM_DIVIDER, null, 0));
      int verifierId = dcContact.getVerifierId();
      if (verifierId != 0) {
        String introducedBy;
        if (verifierId == DcContact.DC_CONTACT_ID_SELF) {
          introducedBy = context.getString(R.string.verified_by_you);
        } else {
          introducedBy =
              context.getString(
                  R.string.verified_by, dcContext.getContact(verifierId).getDisplayName());
        }
        itemData.add(
            new ItemData(
                ITEM_INTRODUCED_BY,
                introducedBy,
                dcContact.isVerified() ? R.drawable.ic_verified : 0));
      } else if (dcContact.isVerified()) {
        String introducedBy = context.getString(R.string.verified_by_unknown);
        itemData.add(new ItemData(ITEM_INTRODUCED_BY, introducedBy, R.drawable.ic_verified));
      }
    }

    notifyDataSetChanged();
  }

  public int ALL_MEDIA_COUNT_MAX = 500;

  public int getAllMediaCount(int chatId) {
    int c =
        dcContext.getChatMedia(chatId, DcMsg.DC_MSG_IMAGE, DcMsg.DC_MSG_GIF, DcMsg.DC_MSG_VIDEO)
            .length;
    if (c < ALL_MEDIA_COUNT_MAX) {
      c += dcContext.getChatMedia(chatId, DcMsg.DC_MSG_AUDIO, DcMsg.DC_MSG_VOICE, 0).length;
    }
    if (c < ALL_MEDIA_COUNT_MAX) {
      c += dcContext.getChatMedia(chatId, DcMsg.DC_MSG_FILE, DcMsg.DC_MSG_WEBXDC, 0).length;
    }
    return c;
  }

  public String getAllMediaCountString(int chatId) {
    final int c = getAllMediaCount(chatId);
    if (c == 0) {
      return context.getString(R.string.none);
    } else if (c >= ALL_MEDIA_COUNT_MAX) {
      return ALL_MEDIA_COUNT_MAX + "+";
    } else {
      return c + "";
    }
  }
}
