/*
 * Copyright (C) 2012 The Guava Authors
 *
 * Licensed 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 com.google.common.collect;

import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkElementIndex;
import static com.google.common.base.Preconditions.checkNotNull;

import com.google.common.annotations.Beta;
import com.google.common.annotations.GwtIncompatible;
import com.google.common.collect.SortedLists.KeyAbsentBehavior;
import com.google.common.collect.SortedLists.KeyPresentBehavior;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.function.Function;
import java.util.stream.Collector;
import org.checkerframework.checker.nullness.qual.Nullable;

/**
 * A {@link RangeMap} whose contents will never change, with many other important properties
 * detailed at {@link ImmutableCollection}.
 *
 * @author Louis Wasserman
 * @since 14.0
 */
@Beta
@GwtIncompatible // NavigableMap
public class ImmutableRangeMap<K extends Comparable<?>, V> implements RangeMap<K, V>, Serializable {

  private static final ImmutableRangeMap<Comparable<?>, Object> EMPTY =
      new ImmutableRangeMap<>(ImmutableList.<Range<Comparable<?>>>of(), ImmutableList.of());

  /**
   * Returns a {@code Collector} that accumulates the input elements into a new {@code
   * ImmutableRangeMap}. As in {@link Builder}, overlapping ranges are not permitted.
   *
   * @since 23.1
   */
  public static <T, K extends Comparable<? super K>, V>
      Collector<T, ?, ImmutableRangeMap<K, V>> toImmutableRangeMap(
          Function<? super T, Range<K>> keyFunction,
          Function<? super T, ? extends V> valueFunction) {
    return CollectCollectors.toImmutableRangeMap(keyFunction, valueFunction);
  }

  /** Returns an empty immutable range map. */
  @SuppressWarnings("unchecked")
  public static <K extends Comparable<?>, V> ImmutableRangeMap<K, V> of() {
    return (ImmutableRangeMap<K, V>) EMPTY;
  }

  /** Returns an immutable range map mapping a single range to a single value. */
  public static <K extends Comparable<?>, V> ImmutableRangeMap<K, V> of(Range<K> range, V value) {
    return new ImmutableRangeMap<>(ImmutableList.of(range), ImmutableList.of(value));
  }

  @SuppressWarnings("unchecked")
  public static <K extends Comparable<?>, V> ImmutableRangeMap<K, V> copyOf(
      RangeMap<K, ? extends V> rangeMap) {
    if (rangeMap instanceof ImmutableRangeMap) {
      return (ImmutableRangeMap<K, V>) rangeMap;
    }
    Map<Range<K>, ? extends V> map = rangeMap.asMapOfRanges();
    ImmutableList.Builder<Range<K>> rangesBuilder = new ImmutableList.Builder<>(map.size());
    ImmutableList.Builder<V> valuesBuilder = new ImmutableList.Builder<V>(map.size());
    for (Entry<Range<K>, ? extends V> entry : map.entrySet()) {
      rangesBuilder.add(entry.getKey());
      valuesBuilder.add(entry.getValue());
    }
    return new ImmutableRangeMap<>(rangesBuilder.build(), valuesBuilder.build());
  }

  /** Returns a new builder for an immutable range map. */
  public static <K extends Comparable<?>, V> Builder<K, V> builder() {
    return new Builder<>();
  }

  /**
   * A builder for immutable range maps. Overlapping ranges are prohibited.
   *
   * @since 14.0
   */
  public static final class Builder<K extends Comparable<?>, V> {
    private final List<Entry<Range<K>, V>> entries;

    public Builder() {
      this.entries = Lists.newArrayList();
    }

    /**
     * Associates the specified range with the specified value.
     *
     * @throws IllegalArgumentException if {@code range} is empty
     */
    @CanIgnoreReturnValue
    public Builder<K, V> put(Range<K> range, V value) {
      checkNotNull(range);
      checkNotNull(value);
      checkArgument(!range.isEmpty(), "Range must not be empty, but was %s", range);
      entries.add(Maps.immutableEntry(range, value));
      return this;
    }

    /** Copies all associations from the specified range map into this builder. */
    @CanIgnoreReturnValue
    public Builder<K, V> putAll(RangeMap<K, ? extends V> rangeMap) {
      for (Entry<Range<K>, ? extends V> entry : rangeMap.asMapOfRanges().entrySet()) {
        put(entry.getKey(), entry.getValue());
      }
      return this;
    }

    @CanIgnoreReturnValue
    Builder<K, V> combine(Builder<K, V> builder) {
      entries.addAll(builder.entries);
      return this;
    }

    /**
     * Returns an {@code ImmutableRangeMap} containing the associations previously added to this
     * builder.
     *
     * @throws IllegalArgumentException if any two ranges inserted into this builder overlap
     */
    public ImmutableRangeMap<K, V> build() {
      Collections.sort(entries, Range.<K>rangeLexOrdering().onKeys());
      ImmutableList.Builder<Range<K>> rangesBuilder = new ImmutableList.Builder<>(entries.size());
      ImmutableList.Builder<V> valuesBuilder = new ImmutableList.Builder<V>(entries.size());
      for (int i = 0; i < entries.size(); i++) {
        Range<K> range = entries.get(i).getKey();
        if (i > 0) {
          Range<K> prevRange = entries.get(i - 1).getKey();
          if (range.isConnected(prevRange) && !range.intersection(prevRange).isEmpty()) {
            throw new IllegalArgumentException(
                "Overlapping ranges: range " + prevRange + " overlaps with entry " + range);
          }
        }
        rangesBuilder.add(range);
        valuesBuilder.add(entries.get(i).getValue());
      }
      return new ImmutableRangeMap<>(rangesBuilder.build(), valuesBuilder.build());
    }
  }

  private final transient ImmutableList<Range<K>> ranges;
  private final transient ImmutableList<V> values;

  ImmutableRangeMap(ImmutableList<Range<K>> ranges, ImmutableList<V> values) {
    this.ranges = ranges;
    this.values = values;
  }

  @Override
  public @Nullable V get(K key) {
    int index =
        SortedLists.binarySearch(
            ranges,
            Range.<K>lowerBoundFn(),
            Cut.belowValue(key),
            KeyPresentBehavior.ANY_PRESENT,
            KeyAbsentBehavior.NEXT_LOWER);
    if (index == -1) {
      return null;
    } else {
      Range<K> range = ranges.get(index);
      return range.contains(key) ? values.get(index) : null;
    }
  }

  @Override
  public @Nullable Entry<Range<K>, V> getEntry(K key) {
    int index =
        SortedLists.binarySearch(
            ranges,
            Range.<K>lowerBoundFn(),
            Cut.belowValue(key),
            KeyPresentBehavior.ANY_PRESENT,
            KeyAbsentBehavior.NEXT_LOWER);
    if (index == -1) {
      return null;
    } else {
      Range<K> range = ranges.get(index);
      return range.contains(key) ? Maps.immutableEntry(range, values.get(index)) : null;
    }
  }

  @Override
  public Range<K> span() {
    if (ranges.isEmpty()) {
      throw new NoSuchElementException();
    }
    Range<K> firstRange = ranges.get(0);
    Range<K> lastRange = ranges.get(ranges.size() - 1);
    return Range.create(firstRange.lowerBound, lastRange.upperBound);
  }

  /**
   * Guaranteed to throw an exception and leave the {@code RangeMap} unmodified.
   *
   * @throws UnsupportedOperationException always
   * @deprecated Unsupported operation.
   */
  @Deprecated
  @Override
  public void put(Range<K> range, V value) {
    throw new UnsupportedOperationException();
  }

  /**
   * Guaranteed to throw an exception and leave the {@code RangeMap} unmodified.
   *
   * @throws UnsupportedOperationException always
   * @deprecated Unsupported operation.
   */
  @Deprecated
  @Override
  public void putCoalescing(Range<K> range, V value) {
    throw new UnsupportedOperationException();
  }

  /**
   * Guaranteed to throw an exception and leave the {@code RangeMap} unmodified.
   *
   * @throws UnsupportedOperationException always
   * @deprecated Unsupported operation.
   */
  @Deprecated
  @Override
  public void putAll(RangeMap<K, V> rangeMap) {
    throw new UnsupportedOperationException();
  }

  /**
   * Guaranteed to throw an exception and leave the {@code RangeMap} unmodified.
   *
   * @throws UnsupportedOperationException always
   * @deprecated Unsupported operation.
   */
  @Deprecated
  @Override
  public void clear() {
    throw new UnsupportedOperationException();
  }

  /**
   * Guaranteed to throw an exception and leave the {@code RangeMap} unmodified.
   *
   * @throws UnsupportedOperationException always
   * @deprecated Unsupported operation.
   */
  @Deprecated
  @Override
  public void remove(Range<K> range) {
    throw new UnsupportedOperationException();
  }

  @Override
  public ImmutableMap<Range<K>, V> asMapOfRanges() {
    if (ranges.isEmpty()) {
      return ImmutableMap.of();
    }
    RegularImmutableSortedSet<Range<K>> rangeSet =
        new RegularImmutableSortedSet<>(ranges, Range.<K>rangeLexOrdering());
    return new ImmutableSortedMap<>(rangeSet, values);
  }

  @Override
  public ImmutableMap<Range<K>, V> asDescendingMapOfRanges() {
    if (ranges.isEmpty()) {
      return ImmutableMap.of();
    }
    RegularImmutableSortedSet<Range<K>> rangeSet =
        new RegularImmutableSortedSet<>(ranges.reverse(), Range.<K>rangeLexOrdering().reverse());
    return new ImmutableSortedMap<>(rangeSet, values.reverse());
  }

  @Override
  public ImmutableRangeMap<K, V> subRangeMap(final Range<K> range) {
    if (checkNotNull(range).isEmpty()) {
      return ImmutableRangeMap.of();
    } else if (ranges.isEmpty() || range.encloses(span())) {
      return this;
    }
    int lowerIndex =
        SortedLists.binarySearch(
            ranges,
            Range.<K>upperBoundFn(),
            range.lowerBound,
            KeyPresentBehavior.FIRST_AFTER,
            KeyAbsentBehavior.NEXT_HIGHER);
    int upperIndex =
        SortedLists.binarySearch(
            ranges,
            Range.<K>lowerBoundFn(),
            range.upperBound,
            KeyPresentBehavior.ANY_PRESENT,
            KeyAbsentBehavior.NEXT_HIGHER);
    if (lowerIndex >= upperIndex) {
      return ImmutableRangeMap.of();
    }
    final int off = lowerIndex;
    final int len = upperIndex - lowerIndex;
    ImmutableList<Range<K>> subRanges =
        new ImmutableList<Range<K>>() {
          @Override
          public int size() {
            return len;
          }

          @Override
          public Range<K> get(int index) {
            checkElementIndex(index, len);
            if (index == 0 || index == len - 1) {
              return ranges.get(index + off).intersection(range);
            } else {
              return ranges.get(index + off);
            }
          }

          @Override
          boolean isPartialView() {
            return true;
          }
        };
    final ImmutableRangeMap<K, V> outer = this;
    return new ImmutableRangeMap<K, V>(subRanges, values.subList(lowerIndex, upperIndex)) {
      @Override
      public ImmutableRangeMap<K, V> subRangeMap(Range<K> subRange) {
        if (range.isConnected(subRange)) {
          return outer.subRangeMap(subRange.intersection(range));
        } else {
          return ImmutableRangeMap.of();
        }
      }
    };
  }

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

  @Override
  public boolean equals(@Nullable Object o) {
    if (o instanceof RangeMap) {
      RangeMap<?, ?> rangeMap = (RangeMap<?, ?>) o;
      return asMapOfRanges().equals(rangeMap.asMapOfRanges());
    }
    return false;
  }

  @Override
  public String toString() {
    return asMapOfRanges().toString();
  }

  /**
   * This class is used to serialize ImmutableRangeMap instances. Serializes the {@link
   * #asMapOfRanges()} form.
   */
  private static class SerializedForm<K extends Comparable<?>, V> implements Serializable {

    private final ImmutableMap<Range<K>, V> mapOfRanges;

    SerializedForm(ImmutableMap<Range<K>, V> mapOfRanges) {
      this.mapOfRanges = mapOfRanges;
    }

    Object readResolve() {
      if (mapOfRanges.isEmpty()) {
        return of();
      } else {
        return createRangeMap();
      }
    }

    Object createRangeMap() {
      Builder<K, V> builder = new Builder<>();
      for (Entry<Range<K>, V> entry : mapOfRanges.entrySet()) {
        builder.put(entry.getKey(), entry.getValue());
      }
      return builder.build();
    }

    private static final long serialVersionUID = 0;
  }

  Object writeReplace() {
    return new SerializedForm<>(asMapOfRanges());
  }

  private static final long serialVersionUID = 0;
}
