// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc.  All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd

import com.google.protobuf.AbstractMessageLite;
import com.google.protobuf.ByteString;
import com.google.protobuf.CodedInputStream;
import com.google.protobuf.ExtensionRegistryLite;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.MessageLite;
import com.google.protobuf.Parser;
import com.google.protobuf.conformance.Conformance;
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.editions.proto2.TestMessagesProto2Editions;
import com.google.protobuf_test_messages.editions.proto3.TestMessagesProto3Editions;
import com.google.protobuf_test_messages.proto3.TestMessagesProto3.TestAllTypesProto3;
import java.nio.ByteBuffer;
import java.util.ArrayList;

class ConformanceJavaLite {
  private int testCount = 0;

  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<T extends MessageLite> {
    public T decode(
        ByteString bytes,
        BinaryDecoderType type,
        Parser<T> parser,
        ExtensionRegistryLite extensions)
        throws InvalidProtocolBufferException {
      switch (type) {
        case BTYE_STRING_DECODER:
        case BYTE_ARRAY_DECODER:
          return parser.parseFrom(bytes, extensions);
        case ARRAY_BYTE_BUFFER_DECODER:
          {
            ByteBuffer buffer = ByteBuffer.allocate(bytes.size());
            bytes.copyTo(buffer);
            buffer.flip();
            return parser.parseFrom(CodedInputStream.newInstance(buffer), extensions);
          }
        case READONLY_ARRAY_BYTE_BUFFER_DECODER:
          {
            return parser.parseFrom(
                CodedInputStream.newInstance(bytes.asReadOnlyByteBuffer()), extensions);
          }
        case DIRECT_BYTE_BUFFER_DECODER:
          {
            ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size());
            bytes.copyTo(buffer);
            buffer.flip();
            return parser.parseFrom(CodedInputStream.newInstance(buffer), extensions);
          }
        case READONLY_DIRECT_BYTE_BUFFER_DECODER:
          {
            ByteBuffer buffer = ByteBuffer.allocateDirect(bytes.size());
            bytes.copyTo(buffer);
            buffer.flip();
            return parser.parseFrom(
                CodedInputStream.newInstance(buffer.asReadOnlyBuffer()), extensions);
          }
        case INPUT_STREAM_DECODER:
          {
            return parser.parseFrom(bytes.newInput(), extensions);
          }
      }
      return null;
    }
  }

  private <T extends MessageLite> T parseBinary(
      ByteString bytes, Parser<T> parser, ExtensionRegistryLite extensions)
      throws InvalidProtocolBufferException {
    ArrayList<T> messages = new ArrayList<>();
    ArrayList<InvalidProtocolBufferException> exceptions = new ArrayList<>();

    for (int i = 0; i < BinaryDecoderType.values().length; i++) {
      messages.add(null);
      exceptions.add(null);
    }
    if (messages.isEmpty()) {
      throw new RuntimeException("binary decoder types missing");
    }

    BinaryDecoder<T> decoder = new BinaryDecoder<>();

    boolean hasMessage = false;
    boolean hasException = false;
    for (int i = 0; i < BinaryDecoderType.values().length; ++i) {
      try {
        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.
      InvalidProtocolBufferException exception = null;
      for (InvalidProtocolBufferException e : exceptions) {
        if (exception != null) {
          exception.addSuppressed(e);
        } else {
          exception = e;
        }
      }
      throw exception;
    }

    // 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 Class<? extends AbstractMessageLite> createTestMessage(String messageType) {
    switch (messageType) {
      case "protobuf_test_messages.proto3.TestAllTypesProto3":
        return TestAllTypesProto3.class;
      case "protobuf_test_messages.proto2.TestAllTypesProto2":
        return TestAllTypesProto2.class;
      case "protobuf_test_messages.editions.proto3.TestAllTypesProto3":
        return TestMessagesProto3Editions.TestAllTypesProto3.class;
      case "protobuf_test_messages.editions.proto2.TestAllTypesProto2":
        return TestMessagesProto2Editions.TestAllTypesProto2.class;
      default:
        throw new IllegalArgumentException(
            "Protobuf request has unexpected payload type: " + messageType);
    }
  }

  private Class<?> createTestFile(String messageType) {
    switch (messageType) {
      case "protobuf_test_messages.proto3.TestAllTypesProto3":
        return TestMessagesProto3.class;
      case "protobuf_test_messages.proto2.TestAllTypesProto2":
        return TestMessagesProto2.class;
      case "protobuf_test_messages.editions.proto3.TestAllTypesProto3":
        return TestMessagesProto3Editions.class;
      case "protobuf_test_messages.editions.proto2.TestAllTypesProto2":
        return TestMessagesProto2Editions.class;
      default:
        throw new IllegalArgumentException(
            "Protobuf request has unexpected payload type: " + messageType);
    }
  }

  @SuppressWarnings("unchecked")
  private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest request) {
    com.google.protobuf.MessageLite testMessage;
    String messageType = request.getMessageType();
    switch (request.getPayloadCase()) {
      case PROTOBUF_PAYLOAD:
        {
          try {
            ExtensionRegistryLite extensions = ExtensionRegistryLite.newInstance();
            createTestFile(messageType)
                .getMethod("registerAllExtensions", ExtensionRegistryLite.class)
                .invoke(null, extensions);
            testMessage =
                parseBinary(
                    request.getProtobufPayload(),
                    (Parser<AbstractMessageLite>)
                        createTestMessage(messageType).getMethod("parser").invoke(null),
                    extensions);
          } catch (InvalidProtocolBufferException e) {
            return Conformance.ConformanceResponse.newBuilder()
                .setParseError(e.getMessage())
                .build();
          } catch (Exception e) {
            throw new RuntimeException(e);
          }
          break;
        }
      case JSON_PAYLOAD:
        {
          return Conformance.ConformanceResponse.newBuilder()
              .setSkipped("Lite runtime does not support JSON format.")
              .build();
        }
      case TEXT_PAYLOAD:
        {
          return Conformance.ConformanceResponse.newBuilder()
              .setSkipped("Lite runtime does not support Text format.")
              .build();
        }
      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:
        return Conformance.ConformanceResponse.newBuilder()
            .setProtobufPayload(testMessage.toByteString())
            .build();

      case JSON:
        return Conformance.ConformanceResponse.newBuilder()
            .setSkipped("Lite runtime does not support JSON format.")
            .build();

      case TEXT_FORMAT:
        return Conformance.ConformanceResponse.newBuilder()
            .setSkipped("Lite runtime does not support Text format.")
            .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 {
    while (doTestIo()) {
      this.testCount++;
    }

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

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