package io.github.droidkaigi.confsched.fragment;

import android.content.Context;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.util.Pair;
import android.view.View;

import org.parceler.Parcels;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import io.github.droidkaigi.confsched.databinding.ItemSessionBinding;
import io.github.droidkaigi.confsched.model.Session;
import io.github.droidkaigi.confsched.widget.BindingHolder;

public class MyScheduleSessionsTabFragment extends SessionsTabFragment {

    @NonNull
    public static MyScheduleSessionsTabFragment newInstance(List<Session> sessions) {
        MyScheduleSessionsTabFragment fragment = new MyScheduleSessionsTabFragment();
        Bundle args = new Bundle();
        args.putParcelable(ARG_SESSIONS, Parcels.wrap(sessions));
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    protected SessionsAdapter createAdapter() {
        return new MyScheduleAdapter(getContext());
    }

    private class MyScheduleAdapter extends SessionsAdapter {

        private Map<Long, Pair<Integer, Integer>> rangeMap = new HashMap<>();

        public MyScheduleAdapter(@NonNull Context context) {
            super(context);
        }

        @Override
        public void onBindViewHolder(BindingHolder<ItemSessionBinding> holder, int position) {
            super.onBindViewHolder(holder, position);

            ItemSessionBinding binding = holder.binding;

            if (isConflicted(position)) {
                binding.txtConflict.setVisibility(View.VISIBLE);
            } else {
                binding.txtConflict.setVisibility(View.GONE);
            }
        }

        private Pair<Integer, Integer> getRangeOfConflictCandidates(int position) {
            Session session = getItem(position);

            if (rangeMap.containsKey(session.stime.getTime())) {
                return rangeMap.get(session.stime.getTime());
            }

            List<Session> candidates = new ArrayList<>();
            candidates.add(session);

            int startOffset = 1;

            while (position - startOffset >= 0) {
                Session s = getItem(position - startOffset);

                if (s.stime.getTime() == session.stime.getTime()) {
                    candidates.add(s);
                } else {
                    break;
                }

                startOffset++;
            }

            for (int offset = 1, count = getItemCount(); position + offset < count; offset++) {
                Session s = getItem(position + offset);

                if (s.stime.getTime() == session.stime.getTime()) {
                    candidates.add(s);
                } else {
                    break;
                }
            }

            Pair<Integer, Integer> range = Pair.create(position - startOffset + 1, candidates.size());
            rangeMap.put(session.stime.getTime(), range);

            return range;
        }

        private boolean isConflicted(int position) {
            Session session = getItem(position);

            if (!session.checked) {
                return false;
            }

            Pair<Integer, Integer> range = getRangeOfConflictCandidates(position);

            for (int i = range.first; i < range.first + range.second; i++) {
                if (i == position) {
                    continue;
                }

                if (getItem(i).checked) {
                    return true;
                }
            }

            return false;
        }

        @Override
        protected void refresh(@NonNull Session session) {
            for (int i = 0, count = getItemCount(); i < count; i++) {
                Session s = getItem(i);
                if (session.equals(s)) {
                    s.checked = session.checked;
                    notifyItemChangedToAffected(i);
                    break;
                }
            }
        }

        private void notifyItemChangedToAffected(int position) {
            Pair<Integer, Integer> range = getRangeOfConflictCandidates(position);
            notifyItemRangeChanged(range.first, range.second);
        }

        @Override
        protected void onLikeChanged(@NonNull Session session, int position) {
            super.onLikeChanged(session, position);

            Pair<Integer, Integer> range = getRangeOfConflictCandidates(position);
            if (range.second > 1) {
                notifyItemRangeChanged(range.first, range.second);
            }
        }
    }

}

@@ -144,16 +144,57 @@
 onNull;%0A
+import android.support.v4.util.ArrayMap;%0A
 import a
@@ -1231,20 +1231,21 @@
 p = new 
-Hash
+Array
 Map%3C%3E();

Modify to use ArrayMap. Take care of performance.