// 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 static com.google.protobuf.WireFormat.WIRETYPE_LENGTH_DELIMITED;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Map;

/** An adapter between the {@link Writer} interface and {@link CodedOutputStream}. */
@ExperimentalApi
final class CodedOutputStreamWriter implements Writer {
  private final CodedOutputStream output;

  public static CodedOutputStreamWriter forCodedOutput(CodedOutputStream output) {
    if (output.wrapper != null) {
      return output.wrapper;
    }
    return new CodedOutputStreamWriter(output);
  }

  private CodedOutputStreamWriter(CodedOutputStream output) {
    this.output = checkNotNull(output, "output");
    this.output.wrapper = this;
  }

  @Override
  public FieldOrder fieldOrder() {
    return FieldOrder.ASCENDING;
  }

  public int getTotalBytesWritten() {
    return output.getTotalBytesWritten();
  }

  @Override
  public void writeSFixed32(int fieldNumber, int value) throws IOException {
    output.writeSFixed32(fieldNumber, value);
  }

  @Override
  public void writeInt64(int fieldNumber, long value) throws IOException {
    output.writeInt64(fieldNumber, value);
  }

  @Override
  public void writeSFixed64(int fieldNumber, long value) throws IOException {
    output.writeSFixed64(fieldNumber, value);
  }

  @Override
  public void writeFloat(int fieldNumber, float value) throws IOException {
    output.writeFloat(fieldNumber, value);
  }

  @Override
  public void writeDouble(int fieldNumber, double value) throws IOException {
    output.writeDouble(fieldNumber, value);
  }

  @Override
  public void writeEnum(int fieldNumber, int value) throws IOException {
    output.writeEnum(fieldNumber, value);
  }

  @Override
  public void writeUInt64(int fieldNumber, long value) throws IOException {
    output.writeUInt64(fieldNumber, value);
  }

  @Override
  public void writeInt32(int fieldNumber, int value) throws IOException {
    output.writeInt32(fieldNumber, value);
  }

  @Override
  public void writeFixed64(int fieldNumber, long value) throws IOException {
    output.writeFixed64(fieldNumber, value);
  }

  @Override
  public void writeFixed32(int fieldNumber, int value) throws IOException {
    output.writeFixed32(fieldNumber, value);
  }

  @Override
  public void writeBool(int fieldNumber, boolean value) throws IOException {
    output.writeBool(fieldNumber, value);
  }

  @Override
  public void writeString(int fieldNumber, String value) throws IOException {
    output.writeString(fieldNumber, value);
  }

  @Override
  public void writeBytes(int fieldNumber, ByteString value) throws IOException {
    output.writeBytes(fieldNumber, value);
  }

  @Override
  public void writeUInt32(int fieldNumber, int value) throws IOException {
    output.writeUInt32(fieldNumber, value);
  }

  @Override
  public void writeSInt32(int fieldNumber, int value) throws IOException {
    output.writeSInt32(fieldNumber, value);
  }

  @Override
  public void writeSInt64(int fieldNumber, long value) throws IOException {
    output.writeSInt64(fieldNumber, value);
  }

  @Override
  public void writeMessage(int fieldNumber, Object value) throws IOException {
    output.writeMessage(fieldNumber, (MessageLite) value);
  }

  @Override
  public void writeMessage(int fieldNumber, Object value, Schema schema) throws IOException {
    output.writeMessage(fieldNumber, (MessageLite) value, schema);
  }

  @Override
  public void writeGroup(int fieldNumber, Object value) throws IOException {
    output.writeGroup(fieldNumber, (MessageLite) value);
  }

  @Override
  public void writeGroup(int fieldNumber, Object value, Schema schema) throws IOException {
    output.writeGroup(fieldNumber, (MessageLite) value, schema);
  }

  @Override
  public void writeStartGroup(int fieldNumber) throws IOException {
    output.writeTag(fieldNumber, WireFormat.WIRETYPE_START_GROUP);
  }

  @Override
  public void writeEndGroup(int fieldNumber) throws IOException {
    output.writeTag(fieldNumber, WireFormat.WIRETYPE_END_GROUP);
  }

  @Override
  public final void writeMessageSetItem(int fieldNumber, Object value) throws IOException {
    if (value instanceof ByteString) {
      output.writeRawMessageSetExtension(fieldNumber, (ByteString) value);
    } else {
      output.writeMessageSetExtension(fieldNumber, (MessageLite) value);
    }
  }

  @Override
  public void writeInt32List(int fieldNumber, List<Integer> value, boolean packed)
      throws IOException {
    if (packed) {
      output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);

      // Compute and write the length of the data.
      int dataSize = 0;
      for (int i = 0; i < value.size(); ++i) {
        dataSize += CodedOutputStream.computeInt32SizeNoTag(value.get(i));
      }
      output.writeUInt32NoTag(dataSize);

      // Write the data itself, without any tags.
      for (int i = 0; i < value.size(); ++i) {
        output.writeInt32NoTag(value.get(i));
      }
    } else {
      for (int i = 0; i < value.size(); ++i) {
        output.writeInt32(fieldNumber, value.get(i));
      }
    }
  }

  @Override
  public void writeFixed32List(int fieldNumber, List<Integer> value, boolean packed)
      throws IOException {
    if (packed) {
      output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);

      // Compute and write the length of the data.
      int dataSize = 0;
      for (int i = 0; i < value.size(); ++i) {
        dataSize += CodedOutputStream.computeFixed32SizeNoTag(value.get(i));
      }
      output.writeUInt32NoTag(dataSize);

      // Write the data itself, without any tags.
      for (int i = 0; i < value.size(); ++i) {
        output.writeFixed32NoTag(value.get(i));
      }
    } else {
      for (int i = 0; i < value.size(); ++i) {
        output.writeFixed32(fieldNumber, value.get(i));
      }
    }
  }

  @Override
  public void writeInt64List(int fieldNumber, List<Long> value, boolean packed) throws IOException {
    if (packed) {
      output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);

      // Compute and write the length of the data.
      int dataSize = 0;
      for (int i = 0; i < value.size(); ++i) {
        dataSize += CodedOutputStream.computeInt64SizeNoTag(value.get(i));
      }
      output.writeUInt32NoTag(dataSize);

      // Write the data itself, without any tags.
      for (int i = 0; i < value.size(); ++i) {
        output.writeInt64NoTag(value.get(i));
      }
    } else {
      for (int i = 0; i < value.size(); ++i) {
        output.writeInt64(fieldNumber, value.get(i));
      }
    }
  }

  @Override
  public void writeUInt64List(int fieldNumber, List<Long> value, boolean packed)
      throws IOException {
    if (packed) {
      output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);

      // Compute and write the length of the data.
      int dataSize = 0;
      for (int i = 0; i < value.size(); ++i) {
        dataSize += CodedOutputStream.computeUInt64SizeNoTag(value.get(i));
      }
      output.writeUInt32NoTag(dataSize);

      // Write the data itself, without any tags.
      for (int i = 0; i < value.size(); ++i) {
        output.writeUInt64NoTag(value.get(i));
      }
    } else {
      for (int i = 0; i < value.size(); ++i) {
        output.writeUInt64(fieldNumber, value.get(i));
      }
    }
  }

  @Override
  public void writeFixed64List(int fieldNumber, List<Long> value, boolean packed)
      throws IOException {
    if (packed) {
      output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);

      // Compute and write the length of the data.
      int dataSize = 0;
      for (int i = 0; i < value.size(); ++i) {
        dataSize += CodedOutputStream.computeFixed64SizeNoTag(value.get(i));
      }
      output.writeUInt32NoTag(dataSize);

      // Write the data itself, without any tags.
      for (int i = 0; i < value.size(); ++i) {
        output.writeFixed64NoTag(value.get(i));
      }
    } else {
      for (int i = 0; i < value.size(); ++i) {
        output.writeFixed64(fieldNumber, value.get(i));
      }
    }
  }

  @Override
  public void writeFloatList(int fieldNumber, List<Float> value, boolean packed)
      throws IOException {
    if (packed) {
      output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);

      // Compute and write the length of the data.
      int dataSize = 0;
      for (int i = 0; i < value.size(); ++i) {
        dataSize += CodedOutputStream.computeFloatSizeNoTag(value.get(i));
      }
      output.writeUInt32NoTag(dataSize);

      // Write the data itself, without any tags.
      for (int i = 0; i < value.size(); ++i) {
        output.writeFloatNoTag(value.get(i));
      }
    } else {
      for (int i = 0; i < value.size(); ++i) {
        output.writeFloat(fieldNumber, value.get(i));
      }
    }
  }

  @Override
  public void writeDoubleList(int fieldNumber, List<Double> value, boolean packed)
      throws IOException {
    if (packed) {
      output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);

      // Compute and write the length of the data.
      int dataSize = 0;
      for (int i = 0; i < value.size(); ++i) {
        dataSize += CodedOutputStream.computeDoubleSizeNoTag(value.get(i));
      }
      output.writeUInt32NoTag(dataSize);

      // Write the data itself, without any tags.
      for (int i = 0; i < value.size(); ++i) {
        output.writeDoubleNoTag(value.get(i));
      }
    } else {
      for (int i = 0; i < value.size(); ++i) {
        output.writeDouble(fieldNumber, value.get(i));
      }
    }
  }

  @Override
  public void writeEnumList(int fieldNumber, List<Integer> value, boolean packed)
      throws IOException {
    if (packed) {
      output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);

      // Compute and write the length of the data.
      int dataSize = 0;
      for (int i = 0; i < value.size(); ++i) {
        dataSize += CodedOutputStream.computeEnumSizeNoTag(value.get(i));
      }
      output.writeUInt32NoTag(dataSize);

      // Write the data itself, without any tags.
      for (int i = 0; i < value.size(); ++i) {
        output.writeEnumNoTag(value.get(i));
      }
    } else {
      for (int i = 0; i < value.size(); ++i) {
        output.writeEnum(fieldNumber, value.get(i));
      }
    }
  }

  @Override
  public void writeBoolList(int fieldNumber, List<Boolean> value, boolean packed)
      throws IOException {
    if (packed) {
      output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);

      // Compute and write the length of the data.
      int dataSize = 0;
      for (int i = 0; i < value.size(); ++i) {
        dataSize += CodedOutputStream.computeBoolSizeNoTag(value.get(i));
      }
      output.writeUInt32NoTag(dataSize);

      // Write the data itself, without any tags.
      for (int i = 0; i < value.size(); ++i) {
        output.writeBoolNoTag(value.get(i));
      }
    } else {
      for (int i = 0; i < value.size(); ++i) {
        output.writeBool(fieldNumber, value.get(i));
      }
    }
  }

  @Override
  public void writeStringList(int fieldNumber, List<String> value) throws IOException {
    if (value instanceof LazyStringList) {
      final LazyStringList lazyList = (LazyStringList) value;
      for (int i = 0; i < value.size(); ++i) {
        writeLazyString(fieldNumber, lazyList.getRaw(i));
      }
    } else {
      for (int i = 0; i < value.size(); ++i) {
        output.writeString(fieldNumber, value.get(i));
      }
    }
  }

  private void writeLazyString(int fieldNumber, Object value) throws IOException {
    if (value instanceof String) {
      output.writeString(fieldNumber, (String) value);
    } else {
      output.writeBytes(fieldNumber, (ByteString) value);
    }
  }

  @Override
  public void writeBytesList(int fieldNumber, List<ByteString> value) throws IOException {
    for (int i = 0; i < value.size(); ++i) {
      output.writeBytes(fieldNumber, value.get(i));
    }
  }

  @Override
  public void writeUInt32List(int fieldNumber, List<Integer> value, boolean packed)
      throws IOException {
    if (packed) {
      output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);

      // Compute and write the length of the data.
      int dataSize = 0;
      for (int i = 0; i < value.size(); ++i) {
        dataSize += CodedOutputStream.computeUInt32SizeNoTag(value.get(i));
      }
      output.writeUInt32NoTag(dataSize);

      // Write the data itself, without any tags.
      for (int i = 0; i < value.size(); ++i) {
        output.writeUInt32NoTag(value.get(i));
      }
    } else {
      for (int i = 0; i < value.size(); ++i) {
        output.writeUInt32(fieldNumber, value.get(i));
      }
    }
  }

  @Override
  public void writeSFixed32List(int fieldNumber, List<Integer> value, boolean packed)
      throws IOException {
    if (packed) {
      output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);

      // Compute and write the length of the data.
      int dataSize = 0;
      for (int i = 0; i < value.size(); ++i) {
        dataSize += CodedOutputStream.computeSFixed32SizeNoTag(value.get(i));
      }
      output.writeUInt32NoTag(dataSize);

      // Write the data itself, without any tags.
      for (int i = 0; i < value.size(); ++i) {
        output.writeSFixed32NoTag(value.get(i));
      }
    } else {
      for (int i = 0; i < value.size(); ++i) {
        output.writeSFixed32(fieldNumber, value.get(i));
      }
    }
  }

  @Override
  public void writeSFixed64List(int fieldNumber, List<Long> value, boolean packed)
      throws IOException {
    if (packed) {
      output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);

      // Compute and write the length of the data.
      int dataSize = 0;
      for (int i = 0; i < value.size(); ++i) {
        dataSize += CodedOutputStream.computeSFixed64SizeNoTag(value.get(i));
      }
      output.writeUInt32NoTag(dataSize);

      // Write the data itself, without any tags.
      for (int i = 0; i < value.size(); ++i) {
        output.writeSFixed64NoTag(value.get(i));
      }
    } else {
      for (int i = 0; i < value.size(); ++i) {
        output.writeSFixed64(fieldNumber, value.get(i));
      }
    }
  }

  @Override
  public void writeSInt32List(int fieldNumber, List<Integer> value, boolean packed)
      throws IOException {
    if (packed) {
      output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);

      // Compute and write the length of the data.
      int dataSize = 0;
      for (int i = 0; i < value.size(); ++i) {
        dataSize += CodedOutputStream.computeSInt32SizeNoTag(value.get(i));
      }
      output.writeUInt32NoTag(dataSize);

      // Write the data itself, without any tags.
      for (int i = 0; i < value.size(); ++i) {
        output.writeSInt32NoTag(value.get(i));
      }
    } else {
      for (int i = 0; i < value.size(); ++i) {
        output.writeSInt32(fieldNumber, value.get(i));
      }
    }
  }

  @Override
  public void writeSInt64List(int fieldNumber, List<Long> value, boolean packed)
      throws IOException {
    if (packed) {
      output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);

      // Compute and write the length of the data.
      int dataSize = 0;
      for (int i = 0; i < value.size(); ++i) {
        dataSize += CodedOutputStream.computeSInt64SizeNoTag(value.get(i));
      }
      output.writeUInt32NoTag(dataSize);

      // Write the data itself, without any tags.
      for (int i = 0; i < value.size(); ++i) {
        output.writeSInt64NoTag(value.get(i));
      }
    } else {
      for (int i = 0; i < value.size(); ++i) {
        output.writeSInt64(fieldNumber, value.get(i));
      }
    }
  }

  @Override
  public void writeMessageList(int fieldNumber, List<?> value) throws IOException {
    for (int i = 0; i < value.size(); ++i) {
      writeMessage(fieldNumber, value.get(i));
    }
  }

  @Override
  public void writeMessageList(int fieldNumber, List<?> value, Schema schema) throws IOException {
    for (int i = 0; i < value.size(); ++i) {
      writeMessage(fieldNumber, value.get(i), schema);
    }
  }

  @Override
  public void writeGroupList(int fieldNumber, List<?> value) throws IOException {
    for (int i = 0; i < value.size(); ++i) {
      writeGroup(fieldNumber, value.get(i));
    }
  }

  @Override
  public void writeGroupList(int fieldNumber, List<?> value, Schema schema) throws IOException {
    for (int i = 0; i < value.size(); ++i) {
      writeGroup(fieldNumber, value.get(i), schema);
    }
  }

  @Override
  public <K, V> void writeMap(int fieldNumber, MapEntryLite.Metadata<K, V> metadata, Map<K, V> map)
      throws IOException {
    if (output.isSerializationDeterministic()) {
      writeDeterministicMap(fieldNumber, metadata, map);
      return;
    }
    for (Map.Entry<K, V> entry : map.entrySet()) {
      output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
      output.writeUInt32NoTag(
          MapEntryLite.computeSerializedSize(metadata, entry.getKey(), entry.getValue()));
      MapEntryLite.writeTo(output, metadata, entry.getKey(), entry.getValue());
    }
  }

  @SuppressWarnings("unchecked")
  private <K, V> void writeDeterministicMap(
      int fieldNumber, MapEntryLite.Metadata<K, V> metadata, Map<K, V> map) throws IOException {
    switch (metadata.keyType) {
      case BOOL:
        V value;
        if ((value = map.get(Boolean.FALSE)) != null) {
          writeDeterministicBooleanMapEntry(
              fieldNumber, /* key= */ false, value, (MapEntryLite.Metadata<Boolean, V>) metadata);
        }
        if ((value = map.get(Boolean.TRUE)) != null) {
          writeDeterministicBooleanMapEntry(
              fieldNumber, /* key= */ true, value, (MapEntryLite.Metadata<Boolean, V>) metadata);
        }
        break;
      case FIXED32:
      case INT32:
      case SFIXED32:
      case SINT32:
      case UINT32:
        writeDeterministicIntegerMap(
            fieldNumber, (MapEntryLite.Metadata<Integer, V>) metadata, (Map<Integer, V>) map);
        break;
      case FIXED64:
      case INT64:
      case SFIXED64:
      case SINT64:
      case UINT64:
        writeDeterministicLongMap(
            fieldNumber, (MapEntryLite.Metadata<Long, V>) metadata, (Map<Long, V>) map);
        break;
      case STRING:
        writeDeterministicStringMap(
            fieldNumber, (MapEntryLite.Metadata<String, V>) metadata, (Map<String, V>) map);
        break;
      default:
        throw new IllegalArgumentException("does not support key type: " + metadata.keyType);
    }
  }

  private <V> void writeDeterministicBooleanMapEntry(
      int fieldNumber, boolean key, V value, MapEntryLite.Metadata<Boolean, V> metadata)
      throws IOException {
    output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
    output.writeUInt32NoTag(MapEntryLite.computeSerializedSize(metadata, key, value));
    MapEntryLite.writeTo(output, metadata, key, value);
  }

  private <V> void writeDeterministicIntegerMap(
      int fieldNumber, MapEntryLite.Metadata<Integer, V> metadata, Map<Integer, V> map)
      throws IOException {
    int[] keys = new int[map.size()];
    int index = 0;
    for (int k : map.keySet()) {
      keys[index++] = k;
    }
    Arrays.sort(keys);
    for (int key : keys) {
      V value = map.get(key);
      output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
      output.writeUInt32NoTag(MapEntryLite.computeSerializedSize(metadata, key, value));
      MapEntryLite.writeTo(output, metadata, key, value);
    }
  }

  private <V> void writeDeterministicLongMap(
      int fieldNumber, MapEntryLite.Metadata<Long, V> metadata, Map<Long, V> map)
      throws IOException {
    long[] keys = new long[map.size()];
    int index = 0;
    for (long k : map.keySet()) {
      keys[index++] = k;
    }
    Arrays.sort(keys);
    for (long key : keys) {
      V value = map.get(key);
      output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
      output.writeUInt32NoTag(MapEntryLite.computeSerializedSize(metadata, key, value));
      MapEntryLite.writeTo(output, metadata, key, value);
    }
  }

  private <V> void writeDeterministicStringMap(
      int fieldNumber, MapEntryLite.Metadata<String, V> metadata, Map<String, V> map)
      throws IOException {
    String[] keys = new String[map.size()];
    int index = 0;
    for (String k : map.keySet()) {
      keys[index++] = k;
    }
    Arrays.sort(keys);
    for (String key : keys) {
      V value = map.get(key);
      output.writeTag(fieldNumber, WIRETYPE_LENGTH_DELIMITED);
      output.writeUInt32NoTag(MapEntryLite.computeSerializedSize(metadata, key, value));
      MapEntryLite.writeTo(output, metadata, key, value);
    }
  }
}
