// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
// https://developers.google.com/protocol-buffers/
//
// 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 static com.google.protobuf.Internal.checkNotNull;

import com.google.protobuf.Descriptors.Descriptor;
import com.google.protobuf.Descriptors.EnumValueDescriptor;
import com.google.protobuf.Descriptors.FieldDescriptor;
import com.google.protobuf.Descriptors.OneofDescriptor;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * An implementation of {@link Message} that can represent arbitrary types,
 * given a {@link Descriptors.Descriptor}.
 *
 * @author kenton@google.com Kenton Varda
 */
public final class DynamicMessage extends AbstractMessage {
  private final Descriptor type;
  private final FieldSet<FieldDescriptor> fields;
  private final FieldDescriptor[] oneofCases;
  private final UnknownFieldSet unknownFields;
  private int memoizedSize = -1;

  /**
   * Construct a {@code DynamicMessage} using the given {@code FieldSet}.
   * oneofCases stores the FieldDescriptor for each oneof to indicate
   * which field is set. Caller should make sure the array is immutable.
   *
   * This constructor is package private and will be used in
   * {@code DynamicMutableMessage} to convert a mutable message to an immutable
   * message.
   */
  DynamicMessage(Descriptor type, FieldSet<FieldDescriptor> fields,
                 FieldDescriptor[] oneofCases,
                 UnknownFieldSet unknownFields) {
    this.type = type;
    this.fields = fields;
    this.oneofCases = oneofCases;
    this.unknownFields = unknownFields;
  }

  /**
   * Get a {@code DynamicMessage} representing the default instance of the
   * given type.
   */
  public static DynamicMessage getDefaultInstance(Descriptor type) {
    int oneofDeclCount = type.toProto().getOneofDeclCount();
    FieldDescriptor[] oneofCases = new FieldDescriptor[oneofDeclCount];
    return new DynamicMessage(type, FieldSet.<FieldDescriptor>emptySet(),
                              oneofCases,
                              UnknownFieldSet.getDefaultInstance());
  }


  /** Parse a message of the given type from the given input stream. */
  public static DynamicMessage parseFrom(Descriptor type,
                                         CodedInputStream input)
                                         throws IOException {
    return newBuilder(type).mergeFrom(input).buildParsed();
  }

  /** Parse a message of the given type from the given input stream. */
  public static DynamicMessage parseFrom(
      Descriptor type,
      CodedInputStream input,
      ExtensionRegistry extensionRegistry)
      throws IOException {
    return newBuilder(type).mergeFrom(input, extensionRegistry).buildParsed();
  }

  /** Parse {@code data} as a message of the given type and return it. */
  public static DynamicMessage parseFrom(Descriptor type, ByteString data)
                                         throws InvalidProtocolBufferException {
    return newBuilder(type).mergeFrom(data).buildParsed();
  }

  /** Parse {@code data} as a message of the given type and return it. */
  public static DynamicMessage parseFrom(Descriptor type, ByteString data,
                                         ExtensionRegistry extensionRegistry)
                                         throws InvalidProtocolBufferException {
    return newBuilder(type).mergeFrom(data, extensionRegistry).buildParsed();
  }

  /** Parse {@code data} as a message of the given type and return it. */
  public static DynamicMessage parseFrom(Descriptor type, byte[] data)
                                         throws InvalidProtocolBufferException {
    return newBuilder(type).mergeFrom(data).buildParsed();
  }

  /** Parse {@code data} as a message of the given type and return it. */
  public static DynamicMessage parseFrom(Descriptor type, byte[] data,
                                         ExtensionRegistry extensionRegistry)
                                         throws InvalidProtocolBufferException {
    return newBuilder(type).mergeFrom(data, extensionRegistry).buildParsed();
  }

  /** Parse a message of the given type from {@code input} and return it. */
  public static DynamicMessage parseFrom(Descriptor type, InputStream input)
                                         throws IOException {
    return newBuilder(type).mergeFrom(input).buildParsed();
  }

  /** Parse a message of the given type from {@code input} and return it. */
  public static DynamicMessage parseFrom(Descriptor type, InputStream input,
                                         ExtensionRegistry extensionRegistry)
                                         throws IOException {
    return newBuilder(type).mergeFrom(input, extensionRegistry).buildParsed();
  }

  /** Construct a {@link Message.Builder} for the given type. */
  public static Builder newBuilder(Descriptor type) {
    return new Builder(type);
  }

  /**
   * Construct a {@link Message.Builder} for a message of the same type as
   * {@code prototype}, and initialize it with {@code prototype}'s contents.
   */
  public static Builder newBuilder(Message prototype) {
    return new Builder(prototype.getDescriptorForType()).mergeFrom(prototype);
  }

  // -----------------------------------------------------------------
  // Implementation of Message interface.

  @Override
  public Descriptor getDescriptorForType() {
    return type;
  }

  @Override
  public DynamicMessage getDefaultInstanceForType() {
    return getDefaultInstance(type);
  }

  @Override
  public Map<FieldDescriptor, Object> getAllFields() {
    return fields.getAllFields();
  }

  @Override
  public boolean hasOneof(OneofDescriptor oneof) {
    verifyOneofContainingType(oneof);
    FieldDescriptor field = oneofCases[oneof.getIndex()];
    if (field == null) {
      return false;
    }
    return true;
  }

  @Override
  public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) {
    verifyOneofContainingType(oneof);
    return oneofCases[oneof.getIndex()];
  }

  @Override
  public boolean hasField(FieldDescriptor field) {
    verifyContainingType(field);
    return fields.hasField(field);
  }

  @Override
  public Object getField(FieldDescriptor field) {
    verifyContainingType(field);
    Object result = fields.getField(field);
    if (result == null) {
      if (field.isRepeated()) {
        result = Collections.emptyList();
      } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
        result = getDefaultInstance(field.getMessageType());
      } else {
        result = field.getDefaultValue();
      }
    }
    return result;
  }

  @Override
  public int getRepeatedFieldCount(FieldDescriptor field) {
    verifyContainingType(field);
    return fields.getRepeatedFieldCount(field);
  }

  @Override
  public Object getRepeatedField(FieldDescriptor field, int index) {
    verifyContainingType(field);
    return fields.getRepeatedField(field, index);
  }

  @Override
  public UnknownFieldSet getUnknownFields() {
    return unknownFields;
  }

  static boolean isInitialized(Descriptor type,
                               FieldSet<FieldDescriptor> fields) {
    // Check that all required fields are present.
    for (final FieldDescriptor field : type.getFields()) {
      if (field.isRequired()) {
        if (!fields.hasField(field)) {
          return false;
        }
      }
    }

    // Check that embedded messages are initialized.
    return fields.isInitialized();
  }

  @Override
  public boolean isInitialized() {
    return isInitialized(type, fields);
  }

  @Override
  public void writeTo(CodedOutputStream output) throws IOException {
    if (type.getOptions().getMessageSetWireFormat()) {
      fields.writeMessageSetTo(output);
      unknownFields.writeAsMessageSetTo(output);
    } else {
      fields.writeTo(output);
      unknownFields.writeTo(output);
    }
  }

  @Override
  public int getSerializedSize() {
    int size = memoizedSize;
    if (size != -1) return size;

    if (type.getOptions().getMessageSetWireFormat()) {
      size = fields.getMessageSetSerializedSize();
      size += unknownFields.getSerializedSizeAsMessageSet();
    } else {
      size = fields.getSerializedSize();
      size += unknownFields.getSerializedSize();
    }

    memoizedSize = size;
    return size;
  }

  @Override
  public Builder newBuilderForType() {
    return new Builder(type);
  }

  @Override
  public Builder toBuilder() {
    return newBuilderForType().mergeFrom(this);
  }

  @Override
  public Parser<DynamicMessage> getParserForType() {
    return new AbstractParser<DynamicMessage>() {
      @Override
      public DynamicMessage parsePartialFrom(
          CodedInputStream input, ExtensionRegistryLite extensionRegistry)
          throws InvalidProtocolBufferException {
        Builder builder = newBuilder(type);
        try {
          builder.mergeFrom(input, extensionRegistry);
        } catch (InvalidProtocolBufferException e) {
          throw e.setUnfinishedMessage(builder.buildPartial());
        } catch (IOException e) {
          throw new InvalidProtocolBufferException(e)
              .setUnfinishedMessage(builder.buildPartial());
        }
        return builder.buildPartial();
      }
    };
  }

  /** Verifies that the field is a field of this message. */
  private void verifyContainingType(FieldDescriptor field) {
    if (field.getContainingType() != type) {
      throw new IllegalArgumentException(
        "FieldDescriptor does not match message type.");
    }
  }

  /** Verifies that the oneof is an oneof of this message. */
  private void verifyOneofContainingType(OneofDescriptor oneof) {
    if (oneof.getContainingType() != type) {
      throw new IllegalArgumentException(
        "OneofDescriptor does not match message type.");
    }
  }

  // =================================================================

  /**
   * Builder for {@link DynamicMessage}s.
   */
  public static final class Builder extends AbstractMessage.Builder<Builder> {
    private final Descriptor type;
    private FieldSet<FieldDescriptor> fields;
    private final FieldDescriptor[] oneofCases;
    private UnknownFieldSet unknownFields;

    /** Construct a {@code Builder} for the given type. */
    private Builder(Descriptor type) {
      this.type = type;
      this.fields = FieldSet.newFieldSet();
      this.unknownFields = UnknownFieldSet.getDefaultInstance();
      this.oneofCases = new FieldDescriptor[type.toProto().getOneofDeclCount()];
      // A MapEntry has all of its fields present at all times.
      if (type.getOptions().getMapEntry()) {
        populateMapEntry();
      }
    }

    private void populateMapEntry() {
      for (FieldDescriptor field : type.getFields()) {
        if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
          fields.setField(field, getDefaultInstance(field.getMessageType()));
        } else {
          fields.setField(field, field.getDefaultValue());
        }
      }
    }

    // ---------------------------------------------------------------
    // Implementation of Message.Builder interface.

    @Override
    public Builder clear() {
      if (fields.isImmutable()) {
        fields = FieldSet.newFieldSet();
      } else {
        fields.clear();
      }
      // A MapEntry has all of its fields present at all times.
      if (type.getOptions().getMapEntry()) {
        populateMapEntry();
      }
      unknownFields = UnknownFieldSet.getDefaultInstance();
      return this;
    }

    @Override
    public Builder mergeFrom(Message other) {
      if (other instanceof DynamicMessage) {
        // This should be somewhat faster than calling super.mergeFrom().
        DynamicMessage otherDynamicMessage = (DynamicMessage) other;
        if (otherDynamicMessage.type != type) {
          throw new IllegalArgumentException(
            "mergeFrom(Message) can only merge messages of the same type.");
        }
        ensureIsMutable();
        fields.mergeFrom(otherDynamicMessage.fields);
        mergeUnknownFields(otherDynamicMessage.unknownFields);
        for (int i = 0; i < oneofCases.length; i++) {
          if (oneofCases[i] == null) {
            oneofCases[i] = otherDynamicMessage.oneofCases[i];
          } else {
            if ((otherDynamicMessage.oneofCases[i] != null)
                && (oneofCases[i] != otherDynamicMessage.oneofCases[i])) {
              fields.clearField(oneofCases[i]);
              oneofCases[i] = otherDynamicMessage.oneofCases[i];
            }
          }
        }
        return this;
      } else {
        return super.mergeFrom(other);
      }
    }

    @Override
    public DynamicMessage build() {
      if (!isInitialized()) {
        throw newUninitializedMessageException(
          new DynamicMessage(type, fields,
              java.util.Arrays.copyOf(oneofCases, oneofCases.length), unknownFields));
      }
      return buildPartial();
    }

    /**
     * Helper for DynamicMessage.parseFrom() methods to call.  Throws
     * {@link InvalidProtocolBufferException} instead of
     * {@link UninitializedMessageException}.
     */
    private DynamicMessage buildParsed() throws InvalidProtocolBufferException {
      if (!isInitialized()) {
        throw newUninitializedMessageException(
          new DynamicMessage(type, fields,
              java.util.Arrays.copyOf(oneofCases, oneofCases.length), unknownFields))
          .asInvalidProtocolBufferException();
      }
      return buildPartial();
    }

    @Override
    public DynamicMessage buildPartial() {
      fields.makeImmutable();
      DynamicMessage result =
        new DynamicMessage(type, fields,
            java.util.Arrays.copyOf(oneofCases, oneofCases.length), unknownFields);
      return result;
    }

    @Override
    public Builder clone() {
      Builder result = new Builder(type);
      result.fields.mergeFrom(fields);
      result.mergeUnknownFields(unknownFields);
      System.arraycopy(oneofCases, 0, result.oneofCases, 0 , oneofCases.length);
      return result;
    }

    @Override
    public boolean isInitialized() {
      return DynamicMessage.isInitialized(type, fields);
    }

    @Override
    public Descriptor getDescriptorForType() {
      return type;
    }

    @Override
    public DynamicMessage getDefaultInstanceForType() {
      return getDefaultInstance(type);
    }

    @Override
    public Map<FieldDescriptor, Object> getAllFields() {
      return fields.getAllFields();
    }

    @Override
    public Builder newBuilderForField(FieldDescriptor field) {
      verifyContainingType(field);

      if (field.getJavaType() != FieldDescriptor.JavaType.MESSAGE) {
        throw new IllegalArgumentException(
          "newBuilderForField is only valid for fields with message type.");
      }

      return new Builder(field.getMessageType());
    }

    @Override
    public boolean hasOneof(OneofDescriptor oneof) {
      verifyOneofContainingType(oneof);
      FieldDescriptor field = oneofCases[oneof.getIndex()];
      if (field == null) {
        return false;
      }
      return true;
    }

    @Override
    public FieldDescriptor getOneofFieldDescriptor(OneofDescriptor oneof) {
      verifyOneofContainingType(oneof);
      return oneofCases[oneof.getIndex()];
    }

    @Override
    public Builder clearOneof(OneofDescriptor oneof) {
      verifyOneofContainingType(oneof);
      FieldDescriptor field = oneofCases[oneof.getIndex()];
      if (field != null) {
        clearField(field);
      }
      return this;
    }

    @Override
    public boolean hasField(FieldDescriptor field) {
      verifyContainingType(field);
      return fields.hasField(field);
    }

    @Override
    public Object getField(FieldDescriptor field) {
      verifyContainingType(field);
      Object result = fields.getField(field);
      if (result == null) {
        if (field.isRepeated()) {
          result = Collections.emptyList();
        } else if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
          result = getDefaultInstance(field.getMessageType());
        } else {
          result = field.getDefaultValue();
        }
      }
      return result;
    }

    @Override
    public Builder setField(FieldDescriptor field, Object value) {
      verifyContainingType(field);
      ensureIsMutable();
      // TODO(xiaofeng): This check should really be put in FieldSet.setField()
      // where all other such checks are done. However, currently
      // FieldSet.setField() permits Integer value for enum fields probably
      // because of some internal features we support. Should figure it out
      // and move this check to a more appropriate place.
      if (field.getType() == FieldDescriptor.Type.ENUM) {
        ensureEnumValueDescriptor(field, value);
      }
      OneofDescriptor oneofDescriptor = field.getContainingOneof();
      if (oneofDescriptor != null) {
        int index = oneofDescriptor.getIndex();
        FieldDescriptor oldField = oneofCases[index];
        if ((oldField != null) && (oldField != field)) {
          fields.clearField(oldField);
        }
        oneofCases[index] = field;
      } else if (field.getFile().getSyntax() == Descriptors.FileDescriptor.Syntax.PROTO3) {
        if (!field.isRepeated()
            && field.getJavaType() != FieldDescriptor.JavaType.MESSAGE
            && value.equals(field.getDefaultValue())) {
          // In proto3, setting a field to its default value is equivalent to clearing the field.
          fields.clearField(field);
          return this;
        }
      }
      fields.setField(field, value);
      return this;
    }

    @Override
    public Builder clearField(FieldDescriptor field) {
      verifyContainingType(field);
      ensureIsMutable();
      OneofDescriptor oneofDescriptor = field.getContainingOneof();
      if (oneofDescriptor != null) {
        int index = oneofDescriptor.getIndex();
        if (oneofCases[index] == field) {
          oneofCases[index] = null;
        }
      }
      fields.clearField(field);
      return this;
    }

    @Override
    public int getRepeatedFieldCount(FieldDescriptor field) {
      verifyContainingType(field);
      return fields.getRepeatedFieldCount(field);
    }

    @Override
    public Object getRepeatedField(FieldDescriptor field, int index) {
      verifyContainingType(field);
      return fields.getRepeatedField(field, index);
    }

    @Override
    public Builder setRepeatedField(FieldDescriptor field, int index, Object value) {
      verifyContainingType(field);
      ensureIsMutable();
      fields.setRepeatedField(field, index, value);
      return this;
    }

    @Override
    public Builder addRepeatedField(FieldDescriptor field, Object value) {
      verifyContainingType(field);
      ensureIsMutable();
      fields.addRepeatedField(field, value);
      return this;
    }

    @Override
    public UnknownFieldSet getUnknownFields() {
      return unknownFields;
    }

    @Override
    public Builder setUnknownFields(UnknownFieldSet unknownFields) {
      if (getDescriptorForType().getFile().getSyntax() == Descriptors.FileDescriptor.Syntax.PROTO3
          && CodedInputStream.getProto3DiscardUnknownFieldsDefault()) {
        return this;
      }
      this.unknownFields = unknownFields;
      return this;
    }

    @Override
    public Builder mergeUnknownFields(UnknownFieldSet unknownFields) {
      if (getDescriptorForType().getFile().getSyntax() == Descriptors.FileDescriptor.Syntax.PROTO3
          && CodedInputStream.getProto3DiscardUnknownFieldsDefault()) {
        return this;
      }
      this.unknownFields =
        UnknownFieldSet.newBuilder(this.unknownFields)
                       .mergeFrom(unknownFields)
                       .build();
      return this;
    }

    /** Verifies that the field is a field of this message. */
    private void verifyContainingType(FieldDescriptor field) {
      if (field.getContainingType() != type) {
        throw new IllegalArgumentException(
          "FieldDescriptor does not match message type.");
      }
    }

    /** Verifies that the oneof is an oneof of this message. */
    private void verifyOneofContainingType(OneofDescriptor oneof) {
      if (oneof.getContainingType() != type) {
        throw new IllegalArgumentException(
          "OneofDescriptor does not match message type.");
      }
    }

    /** Verifies that the value is EnumValueDescriptor and matches Enum Type. */
    private void ensureSingularEnumValueDescriptor(
        FieldDescriptor field, Object value) {
      checkNotNull(value);
      if (!(value instanceof EnumValueDescriptor)) {
        throw new IllegalArgumentException(
          "DynamicMessage should use EnumValueDescriptor to set Enum Value.");
      }
      // TODO(xiaofeng): Re-enable this check after Orgstore is fixed to not
      // set incorrect EnumValueDescriptors.
      // EnumDescriptor fieldType = field.getEnumType();
      // EnumDescriptor fieldValueType = ((EnumValueDescriptor) value).getType();
      // if (fieldType != fieldValueType) {
      //  throw new IllegalArgumentException(String.format(
      //      "EnumDescriptor %s of field doesn't match EnumDescriptor %s of field value",
      //      fieldType.getFullName(), fieldValueType.getFullName()));
      // }
    }

    /** Verifies the value for an enum field. */
    private void ensureEnumValueDescriptor(
        FieldDescriptor field, Object value) {
      if (field.isRepeated()) {
        for (Object item : (List) value) {
          ensureSingularEnumValueDescriptor(field, item);
        }
      } else {
         ensureSingularEnumValueDescriptor(field, value);
      }
    }

    private void ensureIsMutable() {
      if (fields.isImmutable()) {
        fields = fields.clone();
      }
    }

    @Override
    public com.google.protobuf.Message.Builder getFieldBuilder(FieldDescriptor field) {
      // TODO(xiangl): need implementation for dynamic message
      throw new UnsupportedOperationException(
        "getFieldBuilder() called on a dynamic message type.");
    }

    @Override
    public com.google.protobuf.Message.Builder getRepeatedFieldBuilder(FieldDescriptor field,
        int index) {
      throw new UnsupportedOperationException(
        "getRepeatedFieldBuilder() called on a dynamic message type.");
    }
  }
}
