/*
 *
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 *
 */
package org.apache.cassandra.utils;

import java.util.*;

/**
 * A class for iterating sequentially through an ordered collection and efficiently
 * finding the overlapping set of matching intervals.
 *
 * The algorithm is quite simple: the intervals are sorted ascending by both min and max
 * in two separate lists. These lists are walked forwards each time we visit a new point,
 * with the set of intervals in the min-ordered list being added to our set of overlaps,
 * and those in the max-ordered list being removed.
 */
public class OverlapIterator<I extends Comparable<? super I>, V>
{
    // indexing into sortedByMin, tracks the next interval to include
    int nextToInclude;
    final List<Interval<I, V>> sortedByMin;
    // indexing into sortedByMax, tracks the next interval to exclude
    int nextToExclude;
    final List<Interval<I, V>> sortedByMax;
    final Set<V> overlaps = new HashSet<>();
    final Set<V> accessible = Collections.unmodifiableSet(overlaps);

    public OverlapIterator(Collection<Interval<I, V>> intervals)
    {
        sortedByMax = new ArrayList<>(intervals);
        Collections.sort(sortedByMax, Interval.<I, V>maxOrdering());
        // we clone after first sorting by max;  this is quite likely to make sort cheaper, since a.max < b.max
        // generally increases the likelihood that a.min < b.min, so the list may be partially sorted already.
        // this also means if (in future) we sort either collection (or a subset thereof) by the other's comparator
        // all items, including equal, will occur in the same order, including
        sortedByMin = new ArrayList<>(sortedByMax);
        Collections.sort(sortedByMin, Interval.<I, V>minOrdering());
    }

    // move the iterator forwards to the overlaps matching point
    public void update(I point)
    {
        // we don't use binary search here since we expect points to be a superset of the min/max values

        // add those we are now after the start of
        while (nextToInclude < sortedByMin.size() && sortedByMin.get(nextToInclude).min.compareTo(point) <= 0)
            overlaps.add(sortedByMin.get(nextToInclude++).data);
        // remove those we are now after the end of
        while (nextToExclude < sortedByMax.size() && sortedByMax.get(nextToExclude).max.compareTo(point) < 0)
            overlaps.remove(sortedByMax.get(nextToExclude++).data);
    }

    public Set<V> overlaps()
    {
        return accessible;
    }
}
