/*
 * Copyright 2012-present Facebook, Inc.
 *
 * 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.facebook.buck.util.collect;

import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterators;

import java.util.Iterator;
import java.util.NoSuchElementException;

/**
 * {@link Iterable} of an array object that does not make a copy of the array.
 * <p>
 * Designed to be used when it is too expensive to copy an array to a {@link java.util.List} and use
 * the list as an {@link Iterable} instead.
 */
public class ArrayIterable<T> implements Iterable<T> {

  private final T[] array;
  private final int startIndex;
  private final int endIndex;

  /**
   * @param startIndex inclusive
   * @param endIndex exclusive
   */
  private ArrayIterable(T[] array, int startIndex, int endIndex) {
    // No precondition checks here: they have already been performed in the of() method.
    this.array = array;
    this.startIndex = startIndex;
    this.endIndex = endIndex;
  }

  public static <T> Iterable<T> of(T[] array) {
    return of(array, /* startIndex */ 0, /* endIndex */ array.length);
  }

  public static <T> Iterable<T> of(final T[] array, final int startIndex, int endIndex) {
    Preconditions.checkNotNull(array);
    Preconditions.checkPositionIndexes(startIndex, endIndex, array.length);

    // Special-case the empty Iterator with a singleton value.
    if (startIndex >= endIndex) {
      // Note that Collections.emptyIterator().remove() throws an IllegalStateException. We prefer
      // that remove() throws an UnsupportedOperationException for an empty Iterator, so we use
      // ImmutableList instead.
      return ImmutableList.<T>of();
    } else if (endIndex - startIndex == 1) {
      return new Iterable<T>() {
        @Override
        public Iterator<T> iterator() {
          // This always looks up the element in the array in case the user modifies the contents of
          // the array outside of this method. That would probably be a bad thing for the user to
          // do, but this ensures that the behavior is consistent with ArrayIterable.
          return Iterators.singletonIterator(array[startIndex]);
        }
      };
    } else {
      return new ArrayIterable<T>(array, startIndex, endIndex);
    }
  }

  @SuppressWarnings("unchecked") // (Iterator<T>) ImmutableList.of()
  @Override
  public Iterator<T> iterator() {

    return new Iterator<T>() {

      private int index = startIndex;

      @Override
      public boolean hasNext() {
        return index < endIndex;
      }

      @Override
      public T next() {
        if (hasNext()) {
          T element = array[index];
          index++;
          return element;
        } else {
          throw new NoSuchElementException();
        }
      }

      @Override
      public void remove() {
        throw new UnsupportedOperationException();
      }

    };
  }

}

@@ -2845,77 +2845,8 @@
  %7D%0A%0A
-  @SuppressWarnings(%22unchecked%22) // (Iterator%3CT%3E) ImmutableList.of()%0A
   @O

Remove unnecessary @SuppressWarnings.