// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "encode.h"

#include <fuchsia/diagnostics/cpp/fidl.h>
#include <fuchsia/diagnostics/stream/cpp/fidl.h>
#include <lib/zx/clock.h>
#include <zircon/status.h>

#include <iostream>
#include <vector>

#include "fields.h"

namespace streams {
namespace {

const int WORD_SIZE = 8;

size_t padding_8byte(std::vector<uint8_t>* out) {
  size_t length = out->size();
  if (length % WORD_SIZE != 0) {
    out->insert(out->end(), WORD_SIZE - length % WORD_SIZE, 0);
    return WORD_SIZE - length % WORD_SIZE;
  }

  return 0;
}

size_t write_string(const std::string& str, std::vector<uint8_t>* out) {
  out->insert(out->end(), std::begin(str), std::end(str));
  size_t extra_padding = padding_8byte(out);
  return (str.size() + extra_padding) / WORD_SIZE;
}

size_t write_signed_int(int64_t signed_int, std::vector<uint8_t>* out) {
  size_t orig_length = out->size();
  out->resize(out->size() + sizeof(int64_t));
  auto* val_ptr = reinterpret_cast<int64_t*>(out->data() + orig_length);
  *val_ptr = signed_int;
  return sizeof(int64_t) / WORD_SIZE;
}

size_t write_unsigned_int(uint64_t unsigned_int, std::vector<uint8_t>* out) {
  size_t orig_length = out->size();
  out->resize(out->size() + sizeof(uint64_t));
  auto* val_ptr = reinterpret_cast<uint64_t*>(out->data() + orig_length);
  *val_ptr = unsigned_int;
  return sizeof(uint64_t) / WORD_SIZE;
}

size_t write_float(double f, std::vector<uint8_t>* out) {
  size_t orig_length = out->size();
  out->resize(out->size() + sizeof(double));
  auto* val_ptr = reinterpret_cast<double*>(out->data() + orig_length);
  *val_ptr = f;
  return sizeof(double) / WORD_SIZE;
}

size_t log_argument(const std::string& name, const fuchsia::diagnostics::stream::Value& value,
                    std::vector<uint8_t>* out) {
  size_t header_idx = out->size();
  out->resize(header_idx + WORD_SIZE);  // WORD_SIZE=8 is for the header
  size_t s_size = write_string(name, out);
  size_t arg_size = s_size + 1;  // 1 is for the header size

  int type = 0;
  uint64_t value_ref = 0;
  uint64_t bool_val = 0;
  switch (value.Which()) {
    case fuchsia::diagnostics::stream::Value::Tag::kSignedInt:
      type = 3;
      arg_size += write_signed_int(value.signed_int(), out);
      break;

    case fuchsia::diagnostics::stream::Value::Tag::kUnsignedInt:
      type = 4;
      arg_size += write_unsigned_int(value.unsigned_int(), out);
      break;

    case fuchsia::diagnostics::stream::Value::Tag::kFloating:
      type = 5;
      arg_size += write_float(value.floating(), out);
      break;

    case fuchsia::diagnostics::stream::Value::Tag::kText:
      type = 6;
      arg_size += write_string(value.text(), out);
      value_ref = value.text().length() > 0 ? (1 << 15) | value.text().length() : 0;
      break;

    case fuchsia::diagnostics::stream::Value::Tag::kBoolean:
      type = 9;
      bool_val = static_cast<uint64_t>(value.boolean());
      break;

    case fuchsia::diagnostics::stream::Value::Tag::kUnknown:
      break;
    default:
      break;
  }
  uint64_t header = ArgumentFields::Type::Make(type) | ArgumentFields::SizeWords::Make(arg_size) |
                    ArgumentFields::NameRefVal::Make(name.length()) |
                    ArgumentFields::NameRefMSB::Make(name.length() > 0 ? 1 : 0) |
                    StringArgumentFields::ValueRef::Make(value_ref) |
                    BoolArgumentFields::Value::Make(bool_val) | ReservedFields::Value::Make(0);

  std::memcpy(out->data() + header_idx, &header, WORD_SIZE);
  return arg_size;
}

}  // namespace

zx_status_t log_record(const fuchsia::diagnostics::stream::Record& record,
                       std::vector<uint8_t>* out) {
  // Keep index to write header at the end
  size_t idx = out->size();
  out->resize(out->size() + WORD_SIZE);  // WORD_SIZE=8 is header size in bytes

  // Add timstamp
  size_t time_index = out->size();
  zx_time_t time = record.timestamp;
  out->resize(out->size() + sizeof(time));
  std::memcpy(out->data() + time_index, &time, sizeof(time));
  // Add the arguments
  size_t record_size = 2;  // 2 words for Record Header
  for (unsigned long i = 0; i < record.arguments.size(); i++) {
    record_size += log_argument(record.arguments[i].name, record.arguments[i].value, out);
  }
  uint64_t header = HeaderFields::Type::Make(9) | HeaderFields::SizeWords::Make(record_size) |
                    HeaderFields::Reserved::Make(0) | HeaderFields::Severity::Make(record.severity);
  // Set size and write header
  std::memcpy(out->data() + idx, &header, WORD_SIZE);
  return ZX_OK;
}

}  // namespace streams
