// 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.

import com.google.protobuf.AbstractMessage;
import com.google.protobuf.ByteString;
import com.google.protobuf.CodedInputStream;
import com.google.protobuf.ExtensionRegistry;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Parser;
import com.google.protobuf.TextFormat;
import com.google.protobuf.conformance.Conformance;
import com.google.protobuf.util.JsonFormat;
import com.google.protobuf.util.JsonFormat.TypeRegistry;
import com.google.protobuf_test_messages.proto2.TestMessagesProto2;
import com.google.protobuf_test_messages.proto2.TestMessagesProto2.TestAllTypesProto2;
import com.google.protobuf_test_messages.proto3.TestMessagesProto3;
import com.google.protobuf_test_messages.proto3.TestMessagesProto3.TestAllTypesProto3;
import java.nio.ByteBuffer;
import java.util.ArrayList;

class ConformanceJava {
  private int testCount = 0;
  private TypeRegistry typeRegistry;

  private boolean readFromStdin(byte[] buf, int len) throws Exception {
    int ofs = 0;
    while (len > 0) {
      int read = System.in.read(buf, ofs, len);
      if (read == -1) {
        return false;  // EOF
      }
      ofs += read;
      len -= read;
    }

    return true;
  }

  private void writeToStdout(byte[] buf) throws Exception {
    System.out.write(buf);
  }

  // Returns -1 on EOF (the actual values will always be positive).
  private int readLittleEndianIntFromStdin() throws Exception {
    byte[] buf = new byte[4];
    if (!readFromStdin(buf, 4)) {
      return -1;
    }
    return (buf[0] & 0xff)
        | ((buf[1] & 0xff) << 8)
        | ((buf[2] & 0xff) << 16)
        | ((buf[3] & 0xff) << 24);
  }

  private void writeLittleEndianIntToStdout(int val) throws Exception {
    byte[] buf = new byte[4];
    buf[0] = (byte)val;
    buf[1] = (byte)(val >> 8);
    buf[2] = (byte)(val >> 16);
    buf[3] = (byte)(val >> 24);
    writeToStdout(buf);
  }

  private enum BinaryDecoderType {
    BTYE_STRING_DECODER,
    BYTE_ARRAY_DECODER,
    ARRAY_BYTE_BUFFER_DECODER,
    READONLY_ARRAY_BYTE_BUFFER_DECODER,
    DIRECT_BYTE_BUFFER_DECODER,
    READONLY_DIRECT_BYTE_BUFFER_DECODER,
    INPUT_STREAM_DECODER;
  }

  private static class BinaryDecoder <MessageType extends AbstractMessage> {
    public MessageType decode (ByteString bytes, BinaryDecoderType type,
        Parser <MessageType> parser, ExtensionRegistry extensions)
      throws InvalidProtocolBufferException {
      switch (type) {
        case BTYE_STRING_DECODER:
          return parser.parseFrom(bytes, extensions);
        case BYTE_ARRAY_DECODER:
          return parser.parseFrom(bytes.toByteArray(), extensions);
        case ARRAY_BYTE_BUFFER_DECODER: {
          ByteBuffer buffer = ByteBuffer.allocate(bytes.size());
          bytes.copyTo(buffer);
          buffer.flip();
          try {
            return parser.parseFrom(CodedInputStream.newInstance(buffer), extensions);
          } catch (InvalidProtocolBufferException e) {
            throw e;
          }
        }
        case READONLY_ARRAY_BYTE_BUFFER_DECODER: {
          try {
            return parser.parseFrom(
                CodedInputStream.newInstance(bytes.asReadOnlyByteBuffer()), extensions);
          } catch (InvalidProtocolBufferException e) {
            throw e;
          }
        }
        case DIRECT_BYTE_BUFFER_DECODER: {
          ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size());
          bytes.copyTo(buffer);
          buffer.flip();
          try {
            return parser.parseFrom(CodedInputStream.newInstance(buffer), extensions);
          } catch (InvalidProtocolBufferException e) {
            throw e;
          }
        }
        case READONLY_DIRECT_BYTE_BUFFER_DECODER: {
          ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size());
          bytes.copyTo(buffer);
          buffer.flip();
          try {
            return parser.parseFrom(
                CodedInputStream.newInstance(buffer.asReadOnlyBuffer()), extensions);
          } catch (InvalidProtocolBufferException e) {
            throw e;
          }
        }
        case INPUT_STREAM_DECODER: {
          try {
            return parser.parseFrom(bytes.newInput(), extensions);
          } catch (InvalidProtocolBufferException e) {
            throw e;
          }
        }
        default :
          return null;
      }
    }
  }

  private <MessageType extends AbstractMessage> MessageType parseBinary(
      ByteString bytes, Parser <MessageType> parser, ExtensionRegistry extensions)
      throws InvalidProtocolBufferException {
    ArrayList <MessageType> messages = new ArrayList <MessageType> ();
    ArrayList <InvalidProtocolBufferException> exceptions =
        new ArrayList <InvalidProtocolBufferException>();

    for (int i = 0; i < BinaryDecoderType.values().length; i++) {
      messages.add(null);
      exceptions.add(null);
    }
    BinaryDecoder <MessageType> decoder = new BinaryDecoder <MessageType> ();

    boolean hasMessage = false;
    boolean hasException = false;
    for (int i = 0; i < BinaryDecoderType.values().length; ++i) {
      try {
        //= BinaryDecoderType.values()[i].parseProto3(bytes);
        messages.set(i, decoder.decode(bytes, BinaryDecoderType.values()[i], parser, extensions));
        hasMessage = true;
      } catch (InvalidProtocolBufferException e) {
        exceptions.set(i, e);
        hasException = true;
      }
    }

    if (hasMessage && hasException) {
      StringBuilder sb =
          new StringBuilder("Binary decoders disagreed on whether the payload was valid.\n");
      for (int i = 0; i < BinaryDecoderType.values().length; ++i) {
        sb.append(BinaryDecoderType.values()[i].name());
        if (messages.get(i) != null) {
          sb.append(" accepted the payload.\n");
        } else {
          sb.append(" rejected the payload.\n");
        }
      }
      throw new RuntimeException(sb.toString());
    }

    if (hasException) {
      // We do not check if exceptions are equal. Different implementations may return different
      // exception messages. Throw an arbitrary one out instead.
      throw exceptions.get(0);
    }

    // Fast path comparing all the messages with the first message, assuming equality being
    // symmetric and transitive.
    boolean allEqual = true;
    for (int i = 1; i < messages.size(); ++i) {
      if (!messages.get(0).equals(messages.get(i))) {
        allEqual = false;
        break;
      }
    }

    // Slow path: compare and find out all unequal pairs.
    if (!allEqual) {
      StringBuilder sb = new StringBuilder();
      for (int i = 0; i < messages.size() - 1; ++i) {
        for (int j = i + 1; j < messages.size(); ++j) {
          if (!messages.get(i).equals(messages.get(j))) {
            sb.append(BinaryDecoderType.values()[i].name())
                .append(" and ")
                .append(BinaryDecoderType.values()[j].name())
                .append(" parsed the payload differently.\n");
          }
        }
      }
      throw new RuntimeException(sb.toString());
    }

    return messages.get(0);
  }

  private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest request) {
    com.google.protobuf.AbstractMessage testMessage;
    boolean isProto3 = request.getMessageType().equals("protobuf_test_messages.proto3.TestAllTypesProto3");
    boolean isProto2 = request.getMessageType().equals("protobuf_test_messages.proto2.TestAllTypesProto2");

    switch (request.getPayloadCase()) {
      case PROTOBUF_PAYLOAD: {
        if (isProto3) {
          try {
            ExtensionRegistry extensions = ExtensionRegistry.newInstance();
            TestMessagesProto3.registerAllExtensions(extensions);
            testMessage = parseBinary(request.getProtobufPayload(), TestAllTypesProto3.parser(), extensions);
          } catch (InvalidProtocolBufferException e) {
            return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build();
          }
        } else if (isProto2) {
          try {
            ExtensionRegistry extensions = ExtensionRegistry.newInstance();
            TestMessagesProto2.registerAllExtensions(extensions);
            testMessage = parseBinary(request.getProtobufPayload(), TestAllTypesProto2.parser(), extensions);
          } catch (InvalidProtocolBufferException e) {
            return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build();
          }
        } else {
          throw new RuntimeException("Protobuf request doesn't have specific payload type.");
        }
        break;
      }
      case JSON_PAYLOAD: {
        try {
          TestMessagesProto3.TestAllTypesProto3.Builder builder =
              TestMessagesProto3.TestAllTypesProto3.newBuilder();
          JsonFormat.Parser parser = JsonFormat.parser().usingTypeRegistry(typeRegistry);
          if (request.getTestCategory()
              == Conformance.TestCategory.JSON_IGNORE_UNKNOWN_PARSING_TEST) {
            parser = parser.ignoringUnknownFields();
          }
          parser.merge(request.getJsonPayload(), builder);
          testMessage = builder.build();
        } catch (InvalidProtocolBufferException e) {
          return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build();
        }
        break;
      }
      case TEXT_PAYLOAD: {
        if (isProto3) {
          try {
            TestMessagesProto3.TestAllTypesProto3.Builder builder =
                TestMessagesProto3.TestAllTypesProto3.newBuilder();
            TextFormat.merge(request.getTextPayload(), builder);
            testMessage = builder.build();
          } catch (TextFormat.ParseException e) {
              return Conformance.ConformanceResponse.newBuilder()
                  .setParseError(e.getMessage())
                  .build();
          }
        } else if (isProto2) {
          try {
            TestMessagesProto2.TestAllTypesProto2.Builder builder =
                TestMessagesProto2.TestAllTypesProto2.newBuilder();
            TextFormat.merge(request.getTextPayload(), builder);
            testMessage = builder.build();
          } catch (TextFormat.ParseException e) {
              return Conformance.ConformanceResponse.newBuilder()
                  .setParseError(e.getMessage())
                  .build();
          }
        } else {
          throw new RuntimeException("Protobuf request doesn't have specific payload type.");
        }
        break;
      }
      case PAYLOAD_NOT_SET: {
        throw new RuntimeException("Request didn't have payload.");
      }

      default: {
        throw new RuntimeException("Unexpected payload case.");
      }
    }

    switch (request.getRequestedOutputFormat()) {
      case UNSPECIFIED:
        throw new RuntimeException("Unspecified output format.");

      case PROTOBUF: {
        ByteString MessageString = testMessage.toByteString();
        return Conformance.ConformanceResponse.newBuilder().setProtobufPayload(MessageString).build();
      }

      case JSON:
        try {
          return Conformance.ConformanceResponse.newBuilder().setJsonPayload(
              JsonFormat.printer().usingTypeRegistry(typeRegistry).print(testMessage)).build();
        } catch (InvalidProtocolBufferException | IllegalArgumentException e) {
          return Conformance.ConformanceResponse.newBuilder().setSerializeError(
              e.getMessage()).build();
        }

      case TEXT_FORMAT:
        return Conformance.ConformanceResponse.newBuilder().setTextPayload(
            TextFormat.printToString(testMessage)).build();

      default: {
        throw new RuntimeException("Unexpected request output.");
      }
    }
  }

  private boolean doTestIo() throws Exception {
    int bytes = readLittleEndianIntFromStdin();

    if (bytes == -1) {
      return false;  // EOF
    }

    byte[] serializedInput = new byte[bytes];

    if (!readFromStdin(serializedInput, bytes)) {
      throw new RuntimeException("Unexpected EOF from test program.");
    }

    Conformance.ConformanceRequest request =
        Conformance.ConformanceRequest.parseFrom(serializedInput);
    Conformance.ConformanceResponse response = doTest(request);
    byte[] serializedOutput = response.toByteArray();

    writeLittleEndianIntToStdout(serializedOutput.length);
    writeToStdout(serializedOutput);

    return true;
  }

  public void run() throws Exception {
    typeRegistry = TypeRegistry.newBuilder().add(
        TestMessagesProto3.TestAllTypesProto3.getDescriptor()).build();
    while (doTestIo()) {
      this.testCount++;
    }

    System.err.println("ConformanceJava: received EOF from test runner after " +
        this.testCount + " tests");
  }

  public static void main(String[] args) throws Exception {
    new ConformanceJava().run();
  }
}
