/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "src/traceconv/trace_to_text.h"

#include "perfetto/base/logging.h"
#include "perfetto/ext/base/file_utils.h"
#include "perfetto/ext/base/scoped_file.h"
#include "src/protozero/proto_ring_buffer.h"
#include "src/traceconv/trace.descriptor.h"
#include "src/traceconv/utils.h"

#include "protos/perfetto/trace/trace.pbzero.h"
#include "protos/perfetto/trace/trace_packet.pbzero.h"

#include "src/trace_processor/forwarding_trace_parser.h"
#include "src/trace_processor/util/descriptors.h"
#include "src/trace_processor/util/gzip_utils.h"
#include "src/trace_processor/util/protozero_to_text.h"

namespace perfetto {
namespace trace_to_text {
namespace {

using perfetto::trace_processor::DescriptorPool;
using trace_processor::TraceType;
using trace_processor::util::GzipDecompressor;

template <size_t N>
static void WriteToOutput(std::ostream* output, const char (&str)[N]) {
  output->write(str, sizeof(str) - 1);
}

// Online algorithm to covert trace binary to text format.
// Usage:
//  - Feed the trace-binary in a sequence of memblock, and it will continue to
//    write the output in given std::ostream*.
class OnlineTraceToText {
 public:
  OnlineTraceToText(std::ostream* output) : output_(output) {
    pool_.AddFromFileDescriptorSet(kTraceDescriptor.data(),
                                   kTraceDescriptor.size());
  }
  OnlineTraceToText(const OnlineTraceToText&) = delete;
  OnlineTraceToText& operator=(const OnlineTraceToText&) = delete;
  void Feed(const uint8_t* data, size_t len);
  bool ok() const { return ok_; }

 private:
  std::string TracePacketToText(protozero::ConstBytes packet,
                                uint32_t indent_depth);
  void PrintCompressedPackets(protozero::ConstBytes packets);

  bool ok_ = true;
  std::ostream* output_;
  protozero::ProtoRingBuffer ring_buffer_;
  DescriptorPool pool_;
  size_t bytes_processed_ = 0;
  size_t packet_ = 0;
};

std::string OnlineTraceToText::TracePacketToText(protozero::ConstBytes packet,
                                                 uint32_t indent_depth) {
  namespace pb0_to_text = trace_processor::protozero_to_text;
  return pb0_to_text::ProtozeroToText(pool_, ".perfetto.protos.TracePacket",
                                      packet, pb0_to_text::kIncludeNewLines,
                                      indent_depth);
}

void OnlineTraceToText::PrintCompressedPackets(protozero::ConstBytes packets) {
  WriteToOutput(output_, "compressed_packets {\n");
  if (trace_processor::util::IsGzipSupported()) {
    std::vector<uint8_t> whole_data =
        GzipDecompressor::DecompressFully(packets.data, packets.size);
    protos::pbzero::Trace::Decoder decoder(whole_data.data(),
                                           whole_data.size());
    for (auto it = decoder.packet(); it; ++it) {
      WriteToOutput(output_, "  packet {\n");
      std::string text = TracePacketToText(*it, 2);
      output_->write(text.data(), std::streamsize(text.size()));
      WriteToOutput(output_, "\n  }\n");
    }
  } else {
    static const char kErrMsg[] =
        "Cannot decode compressed packets. zlib not enabled in the build "
        "config";
    WriteToOutput(output_, kErrMsg);
    static bool log_once = [] {
      PERFETTO_ELOG("%s", kErrMsg);
      return true;
    }();
    base::ignore_result(log_once);
  }
  WriteToOutput(output_, "}\n");
}

void OnlineTraceToText::Feed(const uint8_t* data, size_t len) {
  ring_buffer_.Append(data, static_cast<size_t>(len));
  while (true) {
    auto token = ring_buffer_.ReadMessage();
    if (token.fatal_framing_error) {
      PERFETTO_ELOG("Failed to tokenize trace packet");
      ok_ = false;
      return;
    }
    if (!token.valid()) {
      // no need to set `ok_ = false` here because this just means
      // we've run out of packets in the ring buffer.
      break;
    }

    if (token.field_id != protos::pbzero::Trace::kPacketFieldNumber) {
      PERFETTO_ELOG("Skipping invalid field");
      continue;
    }
    protos::pbzero::TracePacket::Decoder decoder(token.start, token.len);
    bytes_processed_ += token.len;
    if ((packet_++ & 0x3f) == 0) {
      fprintf(stderr, "Processing trace: %8zu KB%c", bytes_processed_ / 1024,
              kProgressChar);
      fflush(stderr);
    }
    if (decoder.has_compressed_packets()) {
      PrintCompressedPackets(decoder.compressed_packets());
    } else {
      WriteToOutput(output_, "packet {\n");
      protozero::ConstBytes packet = {token.start, token.len};
      std::string text = TracePacketToText(packet, 1 /* indent_depth */);
      output_->write(text.data(), std::streamsize(text.size()));
      WriteToOutput(output_, "\n}\n");
    }
  }
}

class InputReader {
 public:
  InputReader(std::istream* input) : input_(input) {}
  // Request the input-stream to read next |len_limit| bytes and load
  // it in |data|. It also updates the |len| with actual number of bytes loaded
  // in |data|. This can be less than requested |len_limit| if we have reached
  // at the end of the file.
  bool Read(uint8_t* data, uint32_t* len, uint32_t len_limit) {
    if (input_->eof())
      return false;
    input_->read(reinterpret_cast<char*>(data), std::streamsize(len_limit));
    if (input_->bad() || (input_->fail() && !input_->eof())) {
      PERFETTO_ELOG("Failed while reading trace");
      ok_ = false;
      return false;
    }
    *len = uint32_t(input_->gcount());
    return true;
  }
  bool ok() const { return ok_; }

 private:
  std::istream* input_;
  bool ok_ = true;
};

}  // namespace

bool TraceToText(std::istream* input, std::ostream* output) {
  constexpr size_t kMaxMsgSize = protozero::ProtoRingBuffer::kMaxMsgSize;
  std::unique_ptr<uint8_t[]> buffer(new uint8_t[kMaxMsgSize]);
  uint32_t buffer_len = 0;

  InputReader input_reader(input);
  OnlineTraceToText online_trace_to_text(output);

  input_reader.Read(buffer.get(), &buffer_len, kMaxMsgSize);
  TraceType type = trace_processor::GuessTraceType(buffer.get(), buffer_len);

  if (type == TraceType::kGzipTraceType) {
    GzipDecompressor decompressor;
    auto consumer = [&](const uint8_t* data, size_t len) {
      online_trace_to_text.Feed(data, len);
    };
    using ResultCode = GzipDecompressor::ResultCode;
    do {
      ResultCode code =
          decompressor.FeedAndExtract(buffer.get(), buffer_len, consumer);
      if (code == ResultCode::kError || !online_trace_to_text.ok())
        return false;
    } while (input_reader.Read(buffer.get(), &buffer_len, kMaxMsgSize));
    return input_reader.ok();
  } else if (type == TraceType::kProtoTraceType) {
    do {
      online_trace_to_text.Feed(buffer.get(), buffer_len);
      if (!online_trace_to_text.ok())
        return false;
    } while (input_reader.Read(buffer.get(), &buffer_len, kMaxMsgSize));
    return input_reader.ok();
  } else {
    PERFETTO_ELOG("Unrecognised file.");
    return false;
  }
}

}  // namespace trace_to_text
}  // namespace perfetto
