// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// http://code.google.com/p/protobuf/
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
//     * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
//     * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
//     * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

package com.google.protobuf;

import java.util.AbstractList;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;

/**
 * {@code RepeatedFieldBuilder} implements a structure that a protocol
 * message uses to hold a repeated field of other protocol messages. It supports
 * the classical use case of adding immutable {@link Message}'s to the
 * repeated field and is highly optimized around this (no extra memory
 * allocations and sharing of immutable arrays).
 * <br>
 * It also supports the additional use case of adding a {@link Message.Builder}
 * to the repeated field and deferring conversion of that {@code Builder}
 * to an immutable {@code Message}. In this way, it's possible to maintain
 * a tree of {@code Builder}'s that acts as a fully read/write data
 * structure.
 * <br>
 * Logically, one can think of a tree of builders as converting the entire tree
 * to messages when build is called on the root or when any method is called
 * that desires a Message instead of a Builder. In terms of the implementation,
 * the {@code SingleFieldBuilder} and {@code RepeatedFieldBuilder}
 * classes cache messages that were created so that messages only need to be
 * created when some change occured in its builder or a builder for one of its
 * descendants.
 *
 * @param <MType> the type of message for the field
 * @param <BType> the type of builder for the field
 * @param <IType> the common interface for the message and the builder
 *
 * @author jonp@google.com (Jon Perlow)
 */
public class RepeatedFieldBuilder
    <MType extends GeneratedMessage,
     BType extends GeneratedMessage.Builder,
     IType extends MessageOrBuilder>
    implements GeneratedMessage.BuilderParent {

  // Parent to send changes to.
  private GeneratedMessage.BuilderParent parent;

  // List of messages. Never null. It may be immutable, in which case
  // isMessagesListImmutable will be true. See note below.
  private List<MType> messages;

  // Whether messages is an mutable array that can be modified.
  private boolean isMessagesListMutable;

  // List of builders. May be null, in which case, no nested builders were
  // created. If not null, entries represent the builder for that index.
  private List<SingleFieldBuilder<MType, BType, IType>> builders;

  // Here are the invariants for messages and builders:
  // 1. messages is never null and its count corresponds to the number of items
  //    in the repeated field.
  // 2. If builders is non-null, messages and builders MUST always
  //    contain the same number of items.
  // 3. Entries in either array can be null, but for any index, there MUST be
  //    either a Message in messages or a builder in builders.
  // 4. If the builder at an index is non-null, the builder is
  //    authoritative. This is the case where a Builder was set on the index.
  //    Any message in the messages array MUST be ignored.
  // t. If the builder at an index is null, the message in the messages
  //    list is authoritative. This is the case where a Message (not a Builder)
  //    was set directly for an index.

  // Indicates that we've built a message and so we are now obligated
  // to dispatch dirty invalidations. See GeneratedMessage.BuilderListener.
  private boolean isClean;

  // A view of this builder that exposes a List interface of messages. This is
  // initialized on demand. This is fully backed by this object and all changes
  // are reflected in it. Access to any item converts it to a message if it
  // was a builder.
  private MessageExternalList<MType, BType, IType> externalMessageList;

  // A view of this builder that exposes a List interface of builders. This is
  // initialized on demand. This is fully backed by this object and all changes
  // are reflected in it. Access to any item converts it to a builder if it
  // was a message.
  private BuilderExternalList<MType, BType, IType> externalBuilderList;

  // A view of this builder that exposes a List interface of the interface
  // implemented by messages and builders. This is initialized on demand. This
  // is fully backed by this object and all changes are reflected in it.
  // Access to any item returns either a builder or message depending on
  // what is most efficient.
  private MessageOrBuilderExternalList<MType, BType, IType>
      externalMessageOrBuilderList;

  /**
   * Constructs a new builder with an empty list of messages.
   *
   * @param messages the current list of messages
   * @param isMessagesListMutable Whether the messages list is mutable
   * @param parent a listener to notify of changes
   * @param isClean whether the builder is initially marked clean
   */
  public RepeatedFieldBuilder(
      List<MType> messages,
      boolean isMessagesListMutable,
      GeneratedMessage.BuilderParent parent,
      boolean isClean) {
    this.messages = messages;
    this.isMessagesListMutable = isMessagesListMutable;
    this.parent = parent;
    this.isClean = isClean;
  }

  public void dispose() {
    // Null out parent so we stop sending it invalidations.
    parent = null;
  }

  /**
   * Ensures that the list of messages is mutable so it can be updated. If it's
   * immutable, a copy is made.
   */
  private void ensureMutableMessageList() {
    if (!isMessagesListMutable) {
      messages = new ArrayList<MType>(messages);
      isMessagesListMutable = true;
    }
  }

  /**
   * Ensures that the list of builders is not null. If it's null, the list is
   * created and initialized to be the same size as the messages list with
   * null entries.
   */
  private void ensureBuilders() {
    if (this.builders == null) {
      this.builders =
          new ArrayList<SingleFieldBuilder<MType, BType, IType>>(
              messages.size());
      for (int i = 0; i < messages.size(); i++) {
        builders.add(null);
      }
    }
  }

  /**
   * Gets the count of items in the list.
   *
   * @return the count of items in the list.
   */
  public int getCount() {
    return messages.size();
  }

  /**
   * Gets whether the list is empty.
   *
   * @return whether the list is empty
   */
  public boolean isEmpty() {
    return messages.isEmpty();
  }

  /**
   * Get the message at the specified index. If the message is currently stored
   * as a {@code Builder}, it is converted to a {@code Message} by
   * calling {@link Message.Builder#buildPartial} on it.
   *
   * @param index the index of the message to get
   * @return the message for the specified index
   */
  public MType getMessage(int index) {
    return getMessage(index, false);
  }

  /**
   * Get the message at the specified index. If the message is currently stored
   * as a {@code Builder}, it is converted to a {@code Message} by
   * calling {@link Message.Builder#buildPartial} on it.
   *
   * @param index the index of the message to get
   * @param forBuild this is being called for build so we want to make sure
   *     we SingleFieldBuilder.build to send dirty invalidations
   * @return the message for the specified index
   */
  private MType getMessage(int index, boolean forBuild) {
    if (this.builders == null) {
      // We don't have any builders -- return the current Message.
      // This is the case where no builder was created, so we MUST have a
      // Message.
      return messages.get(index);
    }

    SingleFieldBuilder<MType, BType, IType> builder = builders.get(index);
    if (builder == null) {
      // We don't have a builder -- return the current message.
      // This is the case where no builder was created for the entry at index,
      // so we MUST have a message.
      return messages.get(index);

    } else {
      return forBuild ? builder.build() : builder.getMessage();
    }
  }

  /**
   * Gets a builder for the specified index. If no builder has been created for
   * that index, a builder is created on demand by calling
   * {@link Message#toBuilder}.
   *
   * @param index the index of the message to get
   * @return The builder for that index
   */
  public BType getBuilder(int index) {
    ensureBuilders();
    SingleFieldBuilder<MType, BType, IType> builder = builders.get(index);
    if (builder == null) {
      MType message = messages.get(index);
      builder = new SingleFieldBuilder<MType, BType, IType>(
          message, this, isClean);
      builders.set(index, builder);
    }
    return builder.getBuilder();
  }

  /**
   * Gets the base class interface for the specified index. This may either be
   * a builder or a message. It will return whatever is more efficient.
   *
   * @param index the index of the message to get
   * @return the message or builder for the index as the base class interface
   */
  @SuppressWarnings("unchecked")
  public IType getMessageOrBuilder(int index) {
    if (this.builders == null) {
      // We don't have any builders -- return the current Message.
      // This is the case where no builder was created, so we MUST have a
      // Message.
      return (IType) messages.get(index);
    }

    SingleFieldBuilder<MType, BType, IType> builder = builders.get(index);
    if (builder == null) {
      // We don't have a builder -- return the current message.
      // This is the case where no builder was created for the entry at index,
      // so we MUST have a message.
      return (IType) messages.get(index);

    } else {
      return builder.getMessageOrBuilder();
    }
  }

  /**
   * Sets a  message at the specified index replacing the existing item at
   * that index.
   *
   * @param index the index to set.
   * @param message the message to set
   * @return the builder
   */
  public RepeatedFieldBuilder<MType, BType, IType> setMessage(
      int index, MType message) {
    if (message == null) {
      throw new NullPointerException();
    }
    ensureMutableMessageList();
    messages.set(index, message);
    if (builders != null) {
      SingleFieldBuilder<MType, BType, IType> entry =
          builders.set(index, null);
      if (entry != null) {
        entry.dispose();
      }
    }
    onChanged();
    incrementModCounts();
    return this;
  }

  /**
   * Appends the specified element to the end of this list.
   *
   * @param message the message to add
   * @return the builder
   */
  public RepeatedFieldBuilder<MType, BType, IType> addMessage(
      MType message) {
    if (message == null) {
      throw new NullPointerException();
    }
    ensureMutableMessageList();
    messages.add(message);
    if (builders != null) {
      builders.add(null);
    }
    onChanged();
    incrementModCounts();
    return this;
  }

  /**
   * Inserts the specified message at the specified position in this list.
   * Shifts the element currently at that position (if any) and any subsequent
   * elements to the right (adds one to their indices).
   *
   * @param index the index at which to insert the message
   * @param message the message to add
   * @return the builder
   */
  public RepeatedFieldBuilder<MType, BType, IType> addMessage(
      int index, MType message) {
    if (message == null) {
      throw new NullPointerException();
    }
    ensureMutableMessageList();
    messages.add(index, message);
    if (builders != null) {
      builders.add(index, null);
    }
    onChanged();
    incrementModCounts();
    return this;
  }

  /**
   * Appends all of the messages in the specified collection to the end of
   * this list, in the order that they are returned by the specified
   * collection's iterator.
   *
   * @param values the messages to add
   * @return the builder
   */
  public RepeatedFieldBuilder<MType, BType, IType> addAllMessages(
      Iterable<? extends MType> values) {
    for (final MType value : values) {
      if (value == null) {
        throw new NullPointerException();
      }
    }
    if (values instanceof Collection) {
      @SuppressWarnings("unchecked") final
      Collection<MType> collection = (Collection<MType>) values;
      if (collection.size() == 0) {
        return this;
      }
      ensureMutableMessageList();
      for (MType value : values) {
        addMessage(value);
      }
    } else {
      ensureMutableMessageList();
      for (MType value : values) {
        addMessage(value);
      }
    }
    onChanged();
    incrementModCounts();
    return this;
  }

  /**
   * Appends a new builder to the end of this list and returns the builder.
   *
   * @param message the message to add which is the basis of the builder
   * @return the new builder
   */
  public BType addBuilder(MType message) {
    ensureMutableMessageList();
    ensureBuilders();
    SingleFieldBuilder<MType, BType, IType> builder =
        new SingleFieldBuilder<MType, BType, IType>(
            message, this, isClean);
    messages.add(null);
    builders.add(builder);
    onChanged();
    incrementModCounts();
    return builder.getBuilder();
  }

  /**
   * Inserts a new builder at the specified position in this list.
   * Shifts the element currently at that position (if any) and any subsequent
   * elements to the right (adds one to their indices).
   *
   * @param index the index at which to insert the builder
   * @param message the message to add which is the basis of the builder
   * @return the builder
   */
  public BType addBuilder(int index, MType message) {
    ensureMutableMessageList();
    ensureBuilders();
    SingleFieldBuilder<MType, BType, IType> builder =
        new SingleFieldBuilder<MType, BType, IType>(
            message, this, isClean);
    messages.add(index, null);
    builders.add(index, builder);
    onChanged();
    incrementModCounts();
    return builder.getBuilder();
  }

  /**
   * Removes the element at the specified position in this list. Shifts any
   * subsequent elements to the left (subtracts one from their indices).
   * Returns the element that was removed from the list.
   *
   * @param index the index at which to remove the message
   */
  public void remove(int index) {
    ensureMutableMessageList();
    messages.remove(index);
    if (builders != null) {
      SingleFieldBuilder<MType, BType, IType> entry =
          builders.remove(index);
      if (entry != null) {
        entry.dispose();
      }
    }
    onChanged();
    incrementModCounts();
  }

  /**
   * Removes all of the elements from this list.
   * The list will be empty after this call returns.
   */
  public void clear() {
    messages = Collections.emptyList();
    isMessagesListMutable = false;
    if (builders != null) {
      for (SingleFieldBuilder<MType, BType, IType> entry :
          builders) {
        if (entry != null) {
          entry.dispose();
        }
      }
      builders = null;
    }
    onChanged();
    incrementModCounts();
  }

  /**
   * Builds the list of messages from the builder and returns them.
   *
   * @return an immutable list of messages
   */
  public List<MType> build() {
    // Now that build has been called, we are required to dispatch
    // invalidations.
    isClean = true;

    if (!isMessagesListMutable && builders == null) {
      // We still have an immutable list and we never created a builder.
      return messages;
    }

    boolean allMessagesInSync = true;
    if (!isMessagesListMutable) {
      // We still have an immutable list. Let's see if any of them are out
      // of sync with their builders.
      for (int i = 0; i < messages.size(); i++) {
        Message message = messages.get(i);
        SingleFieldBuilder<MType, BType, IType> builder = builders.get(i);
        if (builder != null) {
          if (builder.build() != message) {
            allMessagesInSync = false;
            break;
          }
        }
      }
      if (allMessagesInSync) {
        // Immutable list is still in sync.
        return messages;
      }
    }

    // Need to make sure messages is up to date
    ensureMutableMessageList();
    for (int i = 0; i < messages.size(); i++) {
      messages.set(i, getMessage(i, true));
    }

    // We're going to return our list as immutable so we mark that we can
    // no longer update it.
    messages = Collections.unmodifiableList(messages);
    isMessagesListMutable = false;
    return messages;
  }

  /**
   * Gets a view of the builder as a list of messages. The returned list is live
   * and will reflect any changes to the underlying builder.
   *
   * @return the messages in the list
   */
  public List<MType> getMessageList() {
    if (externalMessageList == null) {
      externalMessageList =
          new MessageExternalList<MType, BType, IType>(this);
    }
    return externalMessageList;
  }

  /**
   * Gets a view of the builder as a list of builders. This returned list is
   * live and will reflect any changes to the underlying builder.
   *
   * @return the builders in the list
   */
  public List<BType> getBuilderList() {
    if (externalBuilderList == null) {
      externalBuilderList =
          new BuilderExternalList<MType, BType, IType>(this);
    }
    return externalBuilderList;
  }

  /**
   * Gets a view of the builder as a list of MessageOrBuilders. This returned
   * list is live and will reflect any changes to the underlying builder.
   *
   * @return the builders in the list
   */
  public List<IType> getMessageOrBuilderList() {
    if (externalMessageOrBuilderList == null) {
      externalMessageOrBuilderList =
          new MessageOrBuilderExternalList<MType, BType, IType>(this);
    }
    return externalMessageOrBuilderList;
  }

  /**
   * Called when a the builder or one of its nested children has changed
   * and any parent should be notified of its invalidation.
   */
  private void onChanged() {
    if (isClean && parent != null) {
      parent.markDirty();

      // Don't keep dispatching invalidations until build is called again.
      isClean = false;
    }
  }

  //@Override (Java 1.6 override semantics, but we must support 1.5)
  public void markDirty() {
    onChanged();
  }

  /**
   * Increments the mod counts so that an ConcurrentModificationException can
   * be thrown if calling code tries to modify the builder while its iterating
   * the list.
   */
  private void incrementModCounts() {
    if (externalMessageList != null) {
      externalMessageList.incrementModCount();
    }
    if (externalBuilderList != null) {
      externalBuilderList.incrementModCount();
    }
    if (externalMessageOrBuilderList != null) {
      externalMessageOrBuilderList.incrementModCount();
    }
  }

  /**
   * Provides a live view of the builder as a list of messages.
   *
   * @param <MType> the type of message for the field
   * @param <BType> the type of builder for the field
   * @param <IType> the common interface for the message and the builder
   */
  private static class MessageExternalList<
      MType extends GeneratedMessage,
      BType extends GeneratedMessage.Builder,
      IType extends MessageOrBuilder>
      extends AbstractList<MType> implements List<MType> {

    RepeatedFieldBuilder<MType, BType, IType> builder;

    MessageExternalList(
        RepeatedFieldBuilder<MType, BType, IType> builder) {
      this.builder = builder;
    }

    public int size() {
      return this.builder.getCount();
    }

    public MType get(int index) {
      return builder.getMessage(index);
    }

    void incrementModCount() {
      modCount++;
    }
  }

  /**
   * Provides a live view of the builder as a list of builders.
   *
   * @param <MType> the type of message for the field
   * @param <BType> the type of builder for the field
   * @param <IType> the common interface for the message and the builder
   */
  private static class BuilderExternalList<
      MType extends GeneratedMessage,
      BType extends GeneratedMessage.Builder,
      IType extends MessageOrBuilder>
      extends AbstractList<BType> implements List<BType> {

    RepeatedFieldBuilder<MType, BType, IType> builder;

    BuilderExternalList(
        RepeatedFieldBuilder<MType, BType, IType> builder) {
      this.builder = builder;
    }

    public int size() {
      return this.builder.getCount();
    }

    public BType get(int index) {
      return builder.getBuilder(index);
    }

    void incrementModCount() {
      modCount++;
    }
  }

  /**
   * Provides a live view of the builder as a list of builders.
   *
   * @param <MType> the type of message for the field
   * @param <BType> the type of builder for the field
   * @param <IType> the common interface for the message and the builder
   */
  private static class MessageOrBuilderExternalList<
      MType extends GeneratedMessage,
      BType extends GeneratedMessage.Builder,
      IType extends MessageOrBuilder>
      extends AbstractList<IType> implements List<IType> {

    RepeatedFieldBuilder<MType, BType, IType> builder;

    MessageOrBuilderExternalList(
        RepeatedFieldBuilder<MType, BType, IType> builder) {
      this.builder = builder;
    }

    public int size() {
      return this.builder.getCount();
    }

    public IType get(int index) {
      return builder.getMessageOrBuilder(index);
    }

    void incrementModCount() {
      modCount++;
    }
  }
}
