package ch.threema.app.adapters;

import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Filter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import com.bumptech.glide.Glide;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

import ch.threema.app.R;
import ch.threema.app.preference.service.PreferenceService;
import ch.threema.app.services.GroupService;
import ch.threema.app.ui.AvatarListItemUtil;
import ch.threema.app.ui.AvatarView;
import ch.threema.app.ui.CheckableConstraintLayout;
import ch.threema.app.ui.listitemholder.AvatarListItemHolder;
import ch.threema.app.utils.AdapterUtil;
import ch.threema.app.utils.NameUtil;
import ch.threema.app.utils.TextExtensionsKt;
import ch.threema.storage.models.group.GroupModelOld;

import static ch.threema.common.JavaCompat.isNullOrBlank;

public class GroupListAdapter extends FilterableListAdapter {
    private final Context context;
    private List<GroupModelOld> values;
    private List<GroupModelOld> ovalues;
    private GroupListFilter groupListFilter;
    private final GroupService groupService;
    private final PreferenceService preferenceService;
    private final FilterResultsListener filterResultsListener;


    public GroupListAdapter(
        Context context,
        List<GroupModelOld> values,
        List<Integer> checkedItems,
        GroupService groupService,
        PreferenceService preferenceService,
        FilterResultsListener filterResultsListener
    ) {
        super(context, R.layout.item_group_list, (List<Object>) (Object) values);

        this.context = context;
        this.values = values;
        this.ovalues = values;
        this.groupService = groupService;
        this.preferenceService = preferenceService;
        this.filterResultsListener = filterResultsListener;

        if (checkedItems != null && !checkedItems.isEmpty()) {
            // restore checked items
            this.checkedItems.addAll(checkedItems);
        }
    }

    @Override
    public View getView(int position, View convertView, ViewGroup parent) {
        CheckableConstraintLayout itemView = (CheckableConstraintLayout) convertView;

        GroupListHolder holder = new GroupListHolder();

        if (convertView == null) {
            // This a new view we inflate the new layout
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            itemView = (CheckableConstraintLayout) inflater.inflate(R.layout.item_group_list, parent, false);

            TextView nameView = itemView.findViewById(R.id.name);
            TextView subjectView = itemView.findViewById(R.id.subject);
            ImageView roleView = itemView.findViewById(R.id.role);
            AvatarView avatarView = itemView.findViewById(R.id.avatar_view);

            holder.nameView = nameView;
            holder.subjectView = subjectView;
            holder.roleView = roleView;
            holder.avatarView = avatarView;

            itemView.setTag(holder);
            itemView.setOnCheckedChangeListener((checkableView, isChecked) -> {
                if (isChecked) {
                    checkedItems.add(((GroupListHolder) checkableView.getTag()).originalPosition);
                } else {
                    checkedItems.remove(((GroupListHolder) checkableView.getTag()).originalPosition);
                }
            });
        } else {
            holder = (GroupListHolder) itemView.getTag();
        }

        final GroupModelOld groupModel = values.get(position);
        holder.originalPosition = ovalues.indexOf(groupModel);

        String filterString = null;
        if (groupListFilter != null) {
            filterString = groupListFilter.getFilterString();
        }

        holder.nameView.setText(
            TextExtensionsKt.highlightMatches(
                NameUtil.getGroupDisplayName(groupModel, this.groupService, preferenceService.getContactNameFormat()),
                context,
                filterString,
                false,
                false
            )
        );
        AdapterUtil.styleGroup(holder.nameView, groupService, groupModel);

        holder.subjectView.setText(this.groupService.getMembersString(groupModel));
        holder.roleView.setImageResource(groupService.isGroupCreator(groupModel)
            ? (groupService.isNotesGroup(groupModel) ? R.drawable.ic_spiral_bound_booklet_outline : R.drawable.ic_group_outline)
            : R.drawable.ic_group_filled);

        // load avatars asynchronously
        AvatarListItemUtil.loadAvatar(
            groupModel,
            this.groupService,
            holder,
            Glide.with(context)
        );

        ((ListView) parent).setItemChecked(position, checkedItems.contains(holder.originalPosition));

        return itemView;
    }

    private static class GroupListHolder extends AvatarListItemHolder {
        public TextView nameView;
        private TextView subjectView;
        private ImageView roleView;
        private int originalPosition;
    }

    public class GroupListFilter extends Filter {
        String filterString = null;

        @Override
        protected FilterResults performFiltering(CharSequence constraint) {
            FilterResults results = new FilterResults();

            if (constraint == null || constraint.length() == 0) {
                // no filtering
                filterString = null;
                results.values = ovalues;
                results.count = ovalues.size();
            } else {
                // perform filtering
                List<GroupModelOld> nGroupList = new ArrayList<GroupModelOld>();
                filterString = constraint.toString();

                for (GroupModelOld groupModel : ovalues) {
                    if (
                        NameUtil.getGroupDisplayName(
                            groupModel,
                            groupService,
                            preferenceService.getContactNameFormat()
                        ).toUpperCase().contains(filterString.toUpperCase())
                    ) {
                        nGroupList.add(groupModel);
                    }
                }
                results.values = nGroupList;
                results.count = nGroupList.size();
            }
            return results;
        }

        @Override
        protected void publishResults(CharSequence constraint, FilterResults results) {
            values = (List<GroupModelOld>) results.values;
            if (filterResultsListener != null) {
                filterResultsListener.onResultsAvailable(isNullOrBlank(constraint) ? 0 : results.count);
            }
            notifyDataSetChanged();
        }

        public String getFilterString() {
            return filterString;
        }
    }

    @Override
    public Filter getFilter() {
        if (groupListFilter == null)
            groupListFilter = new GroupListFilter();

        return groupListFilter;
    }

    @Override
    public int getCount() {
        return values != null ? values.size() : 0;
    }

    @Override
    public HashSet<GroupModelOld> getCheckedItems() {
        HashSet<GroupModelOld> groups = new HashSet<>();
        GroupModelOld groupModel;

        for (int position : checkedItems) {
            groupModel = ovalues.get(position);
            if (groupModel != null) {
                groups.add(groupModel);
            }
        }
        return groups;
    }

    @Override
    public GroupModelOld getClickedItem(View v) {
        return ovalues.get(((GroupListHolder) v.getTag()).originalPosition);
    }
}
