package org.apache.cassandra.db.commitlog;

import java.io.IOException;
import java.util.*;

import com.google.common.collect.ImmutableSortedMap;

import org.apache.cassandra.db.TypeSizes;
import org.apache.cassandra.io.ISerializer;
import org.apache.cassandra.io.util.DataInputPlus;
import org.apache.cassandra.io.util.DataOutputPlus;

/**
 * An immutable set of closed intervals, stored in normalized form (i.e. where overlapping intervals are converted
 * to a single interval covering both).
 *
 * The set is stored as a sorted map from interval starts to the corresponding end. The map satisfies
 *   {@code curr().getKey() <= curr().getValue() < next().getKey()}
 */
public class IntervalSet<T extends Comparable<T>>
{
    @SuppressWarnings({ "rawtypes", "unchecked" })
    private static final IntervalSet EMPTY = new IntervalSet(ImmutableSortedMap.of());

    final private NavigableMap<T, T> ranges;

    private IntervalSet(ImmutableSortedMap<T, T> ranges)
    {
        this.ranges = ranges;
    }

    /**
     * Construct new set containing the interval with the given start and end position.
     */
    public IntervalSet(T start, T end)
    {
        this(ImmutableSortedMap.of(start, end));
    }

    @SuppressWarnings("unchecked")
    public static <T extends Comparable<T>> IntervalSet<T> empty()
    {
        return EMPTY;
    }

    public boolean contains(T position)
    {
        // closed (i.e. inclusive) intervals
        Map.Entry<T, T> range = ranges.floorEntry(position);
        return range != null && position.compareTo(range.getValue()) <= 0;
    }

    public boolean isEmpty()
    {
        return ranges.isEmpty();
    }

    public Optional<T> lowerBound()
    {
        return isEmpty() ? Optional.empty() : Optional.of(ranges.firstKey());
    }

    public Optional<T> upperBound()
    {
        return isEmpty() ? Optional.empty() : Optional.of(ranges.lastEntry().getValue());
    }

    public Collection<T> starts()
    {
        return ranges.keySet();
    }

    public Collection<T> ends()
    {
        return ranges.values();
    }

    public String toString()
    {
        return ranges.toString();
    }

    @Override
    public int hashCode()
    {
        return ranges.hashCode();
    }

    @Override
    public boolean equals(Object obj)
    {
        return obj instanceof IntervalSet && ranges.equals(((IntervalSet<?>) obj).ranges);
    }

    public static final <T extends Comparable<T>> ISerializer<IntervalSet<T>> serializer(ISerializer<T> pointSerializer)
    {
        return new ISerializer<IntervalSet<T>>()
        {
            public void serialize(IntervalSet<T> intervals, DataOutputPlus out) throws IOException
            {
                out.writeInt(intervals.ranges.size());
                for (Map.Entry<T, T> en : intervals.ranges.entrySet())
                {
                    pointSerializer.serialize(en.getKey(), out);
                    pointSerializer.serialize(en.getValue(), out);
                }
            }

            public IntervalSet<T> deserialize(DataInputPlus in) throws IOException
            {
                int count = in.readInt();
                NavigableMap<T, T> ranges = new TreeMap<>();
                for (int i = 0; i < count; ++i)
                    ranges.put(pointSerializer.deserialize(in), pointSerializer.deserialize(in));
                return new IntervalSet<T>(ImmutableSortedMap.copyOfSorted(ranges));
            }

            public long serializedSize(IntervalSet<T> intervals)
            {
                long size = TypeSizes.sizeof(intervals.ranges.size());
                for (Map.Entry<T, T> en : intervals.ranges.entrySet())
                {
                    size += pointSerializer.serializedSize(en.getKey());
                    size += pointSerializer.serializedSize(en.getValue());
                }
                return size;
            }
        };
    };

    /**
     * Builder of interval sets, applying the necessary normalization while adding ranges.
     *
     * Data is stored as above, as a sorted map from interval starts to the corresponding end, which satisfies
     *   {@code curr().getKey() <= curr().getValue() < next().getKey()}
     */
    static public class Builder<T extends Comparable<T>>
    {
        final NavigableMap<T, T> ranges;

        public Builder()
        {
            this.ranges = new TreeMap<>();
        }

        public Builder(T start, T end)
        {
            this();
            assert start.compareTo(end) <= 0;
            ranges.put(start, end);
        }

        /**
         * Add an interval to the set and perform normalization.
         */
        public void add(T start, T end)
        {
            assert start.compareTo(end) <= 0;
            // extend ourselves to cover any ranges we overlap
            // record directly preceding our end may extend past us, so take the max of our end and its
            Map.Entry<T, T> extend = ranges.floorEntry(end);
            if (extend != null && extend.getValue().compareTo(end) > 0)
                end = extend.getValue();

            // record directly preceding our start may extend into us; if it does, we take it as our start
            extend = ranges.lowerEntry(start);
            if (extend != null && extend.getValue().compareTo(start) >= 0)
                start = extend.getKey();

            // remove all covered intervals
            // since we have adjusted start and end to cover the ones that would be only partially covered, we
            // are certain that anything whose start falls within the span is completely covered
            ranges.subMap(start, end).clear();
            // add the new interval
            ranges.put(start, end);
        }

        public void addAll(IntervalSet<T> otherSet)
        {
            for (Map.Entry<T, T> en : otherSet.ranges.entrySet())
            {
                add(en.getKey(), en.getValue());
            }
        }

        public IntervalSet<T> build()
        {
            return new IntervalSet<T>(ImmutableSortedMap.copyOfSorted(ranges));
        }
    }

}