#!/usr/bin/env python
# Copyright (c) 2014,2016 - Adjacent Link LLC, Bridgewater, New Jersey
# All rights reserved.
#
# 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 Adjacent Link LLC 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.
#
# See toplevel COPYING for more information.
#

import sys
import struct
import uuid
import otestpoint.interface.probereport_pb2
from otestpoint.interface import make_measurement_operator
from optparse import OptionParser

usage = "%prog [OPTION]..."

description="""Print probe meta information or formatted probe data from probe
stream format input. Unless otherwise specified, input is read from
stdin."""

epilog="""Probe stream format uses length prefix framing, where the length of
the message is output as an unsigned 32-bit integer value (4 bytes) in
network byte order preceding the output of the serialized message. All
probe messages are serialized OpenTestPopint::ProbeReport protobuf
messages."""

optionParser = OptionParser(usage=usage,
                            description=description,
                            epilog=epilog)

optionParser.add_option("-o",
                        "--outfile",
                        type="string",
                        dest="outfile",
                        help="write output to specified file")


optionParser.add_option("-i",
                        "--infile",
                        type="string",
                        dest="infile",
                        help="read input from specified file")

(options, args) = optionParser.parse_args()

if len(args) > 0:
  print "invalid usage"
  exit(1)

if options.infile:
  ifd = open(options.infile,"r")
else:
  ifd = sys.stdin

if options.outfile:
  ofd = open(options.outfile,"w")
else:
  ofd = sys.stdout

operators = {}

try:
  while True:
    data=""

    while len(data) != 4:
      val = ifd.read(4-len(data))
      if len(val):
        data += val;
      else:
        exit(0)

    msgLength, = struct.unpack("!L",data);

    data = ""

    while(len(data) != msgLength):
      val = ifd.read(msgLength-len(data));
      if len(val):
        data += val;
      else:
        exit(0)

      report = otestpoint.interface.probereport_pb2.ProbeReport()

      report.ParseFromString(data)

      print >>ofd, "[%s]" % report.timestamp, "%s/%d" % (report.tag,report.index),uuid.UUID(bytes=report.uuid)
      print >>ofd, report.data.module,report.data.name,"v%d" % report.data.version,len(report.data.blob),"bytes"
      
      if report.data.name not in operators:
        MeasurementOperator = make_measurement_operator(report.data.module,
                                                        report.data.name)

        if MeasurementOperator != None:
          operator = MeasurementOperator()
        else:
          operator = None
              
        operators[report.data.name] = operator
        
      else:
        operator = operators[report.data.name]
              
      if operator != None:
        measurement = operator.create(report.data.blob)
        print >>ofd, operator.pprint(measurement)

except KeyboardInterrupt:
  pass

print >>sys.stderr

