import com.google.protobuf.ByteString;
import com.google.protobuf.AbstractMessage;
import com.google.protobuf.Parser;
import com.google.protobuf.CodedInputStream;
import com.google.protobuf.conformance.Conformance;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf_test_messages.proto3.TestMessagesProto3;
import com.google.protobuf_test_messages.proto3.TestMessagesProto3.TestAllTypesProto3;
import com.google.protobuf_test_messages.proto2.TestMessagesProto2;
import com.google.protobuf_test_messages.proto2.TestMessagesProto2.TestAllTypesProto2;
import com.google.protobuf.ExtensionRegistry;
import com.google.protobuf.util.JsonFormat;
import com.google.protobuf.util.JsonFormat.TypeRegistry;
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().usingTypeRegistry(typeRegistry)
              .merge(request.getJsonPayload(), builder);
          testMessage = builder.build();
        } catch (InvalidProtocolBufferException e) {
          return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build();
        }
        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();
        }

      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();
  }
}
