#!/usr/bin/env node
// 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.

var conformance = require('conformance_pb');
var test_messages_proto3 = require('google/protobuf/test_messages_proto3_pb');
var test_messages_proto2 = require('google/protobuf/test_messages_proto2_pb');
var fs = require('fs');

var testCount = 0;

function doTest(request) {
  var testMessage;
  var response = new conformance.ConformanceResponse();

  try {
    if (request.getRequestedOutputFormat() == conformance.WireFormat.JSON) {
      response.setSkipped("JSON not supported.");
      return response;
    }

    if (request.getRequestedOutputFormat() == conformance.WireFormat.TEXT_FORMAT) {
      response.setSkipped('Text format is not supported as output format.');
      return response;
    }

    switch (request.getPayloadCase()) {
      case conformance.ConformanceRequest.PayloadCase.PROTOBUF_PAYLOAD: {
        if (request.getMessageType() == "protobuf_test_messages.proto3.TestAllTypesProto3") {
          try {
            testMessage = test_messages_proto3.TestAllTypesProto3.deserializeBinary(
                request.getProtobufPayload());
          } catch (err) {
            response.setParseError(err.toString());
            return response;
          }
        } else if (request.getMessageType() == "protobuf_test_messages.proto2.TestAllTypesProto2"){
          try {
            testMessage = test_messages_proto2.TestAllTypesProto2.deserializeBinary(
                request.getProtobufPayload());
          } catch (err) {
            response.setParseError(err.toString());
            return response;
          }
        } else {
          throw "Protobuf request doesn\'t have specific payload type";
        }
      } break;

      case conformance.ConformanceRequest.PayloadCase.JSON_PAYLOAD:
        response.setSkipped("JSON not supported.");
        return response;

	  case conformance.ConformanceRequest.PayloadCase.TEXT_PAYLOAD:
	    response.setSkipped("Text format not supported.");
        return response;
		
      case conformance.ConformanceRequest.PayloadCase.PAYLOAD_NOT_SET:
        response.setRuntimeError("Request didn't have payload");
        return response;
    }

    switch (request.getRequestedOutputFormat()) {
      case conformance.WireFormat.UNSPECIFIED:
        response.setRuntimeError("Unspecified output format");
        return response;

      case conformance.WireFormat.PROTOBUF:
        response.setProtobufPayload(testMessage.serializeBinary());

      case conformance.WireFormat.JSON:
        response.setSkipped("JSON not supported.");
        return response;

      default:
        throw "Request didn't have requested output format";
    }
  } catch (err) {
    response.setRuntimeError(err.toString());
  }

  return response;
}

function onEof(totalRead) {
  if (totalRead == 0) {
    return undefined;
  } else {
    throw "conformance_nodejs: premature EOF on stdin.";
  }
}

// Utility function to read a buffer of N bytes.
function readBuffer(bytes) {
  var buf = new Buffer(bytes);
  var totalRead = 0;
  while (totalRead < bytes) {
    var read = 0;
    try {
      read = fs.readSync(process.stdin.fd, buf, totalRead, bytes - totalRead);
    } catch (e) {
      if (e.code == 'EOF') {
        return onEof(totalRead)
      } else if (e.code == 'EAGAIN') {
      } else {
        throw "conformance_nodejs: Error reading from stdin." + e;
      }
    }

    totalRead += read;
  }

  return buf;
}

function writeBuffer(buffer) {
  var totalWritten = 0;
  while (totalWritten < buffer.length) {
    totalWritten += fs.writeSync(
        process.stdout.fd, buffer, totalWritten, buffer.length - totalWritten);
  }
}

// Returns true if the test ran successfully, false on legitimate EOF.
// If EOF is encountered in an unexpected place, raises IOError.
function doTestIo() {
  var lengthBuf = readBuffer(4);
  if (!lengthBuf) {
    return false;
  }

  var length = lengthBuf.readInt32LE(0);
  var serializedRequest = readBuffer(length);
  if (!serializedRequest) {
    throw "conformance_nodejs: Failed to read request.";
  }

  serializedRequest = new Uint8Array(serializedRequest);
  var request =
      conformance.ConformanceRequest.deserializeBinary(serializedRequest);
  var response = doTest(request);

  var serializedResponse = response.serializeBinary();

  lengthBuf = new Buffer(4);
  lengthBuf.writeInt32LE(serializedResponse.length, 0);
  writeBuffer(lengthBuf);
  writeBuffer(new Buffer(serializedResponse));

  testCount += 1

  return true;
}

while (true) {
  if (!doTestIo()) {
    console.error('conformance_nodejs: received EOF from test runner ' +
                  "after " + testCount + " tests, exiting")
    break;
  }
}
