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

#ifndef MOJO_SERVICES_FLOG_CPP_FLOG_H_
#define MOJO_SERVICES_FLOG_CPP_FLOG_H_

#include <atomic>
#include <memory>

#include "mojo/public/cpp/application/application_impl.h"
#include "mojo/public/cpp/application/connect.h"
#include "mojo/public/cpp/bindings/array.h"
#include "mojo/public/cpp/bindings/message.h"
#include "mojo/public/cpp/environment/logging.h"
#include "mojo/public/cpp/system/time.h"
#include "mojo/services/flog/interfaces/flog.mojom.h"

namespace mojo {
namespace flog {

//
// FORMATTED LOGGING
//
// The Flog class and associated macros provide a means of logging 'formatted'
// log messages serialized by Mojo. Flog uses an instance of FlogLogger to
// log events to the FlogService. Messages pulled from the FlogService can be
// deserialized using Mojo on behalf of log visualization and analysis tools.
//
// Message logging is performed using a 'channel', which is bound to a Mojo
// proxy for a particular interface. Mojo interfaces used for this purpose must
// be request-only, meaning the constituent methods must not have responses.
//
// Assume that we've defined the following interface:
//
//     [ServiceName="my_namespace::MyFlogChannelInterface"]
//     interface MyFlogChannelInterface {
//       Thing1(int64 a, int32 b);
//       Thing2(string c);
//     };
//
// Note that the ServiceName annotation is required.
//
// A channel instance may be defined, typically as a member of a class, as
// follows:
//
//     FLOG_CHANNEL(MyFlogChannelInterface, my_flog_channel_instance_);
//
// If NDEBUG is defined, this compiles to nothing. Otherwise, it declares and
// initializes my_flog_channel_instance, which can be used via the FLOG macro:
//
//     FLOG(my_flog_channel_instance_, Thing1(1234, 5678));
//     FLOG(my_flog_channel_instance_, Thing2("To the lifeboats!"));
//
// These invocations compile to nothing if NDEBUG is defined. Otherwise, they
// log messages to the channel represented by my_flog_channel_instance.
//
// FLOG_CHANNEL_DECL produces only a declaration for cases in which a channel
// must be declared but not defined (e.g. as a static class member).
//
// Logging to a channel does nothing unless the Flog class has been initialized
// with a call to Flog::Initialize. Flog::Initialize provides a FlogLogger
// implementation to be used for logging. Typically, this implementation would
// be acquired from the FlogService using CreateLogger.
//

#if defined(NDEBUG)

#define FLOG_INITIALIZE(app_or_logger, label) ((void)0)
#define FLOG_DESTROY() ((void)0)
#define FLOG_CHANNEL(channel_type, channel_name)
#define FLOG_CHANNEL_DECL(channel_type, channel_name)
#define FLOG(channel_name, call) ((void)0)
#define FLOG_ID(channel_name) 0

#else

#define FLOG_INITIALIZE(app_or_logger, label) \
  mojo::flog::Flog::Initialize(app_or_logger, label)

#define FLOG_DESTROY() mojo::flog::Flog::Destroy()

#define FLOG_CHANNEL(channel_type, channel_name)                      \
  std::unique_ptr<mojo::flog::FlogProxy<channel_type>> channel_name = \
      mojo::flog::FlogProxy<channel_type>::Create()

#define FLOG_CHANNEL_DECL(channel_type, channel_name) \
  std::unique_ptr<mojo::flog::FlogProxy<channel_type>> channel_name

#define FLOG(channel_name, call) channel_name->call

#define FLOG_ID(channel_name) channel_name->channel()->id()

#endif

// Thread-safe logger for all channels in a given process.
class Flog {
 public:
  static void Initialize(ApplicationImpl* app, const std::string& label) {
    MOJO_DCHECK(!logger_);
    FlogServicePtr flog_service;
    FlogLoggerPtr flog_logger;
    ConnectToService(app->shell(), "mojo:flog", GetProxy(&flog_service));
    flog_service->CreateLogger(GetProxy(&flog_logger), label);
    logger_ = flog_logger.Pass();
  }

  // Sets the flog logger singleton.
  static void Initialize(FlogLoggerPtr flog_logger) {
    MOJO_DCHECK(!logger_);
    logger_ = flog_logger.Pass();
  }

  // Deletes the flog logger singleton.
  static void Destroy() {
    MOJO_DCHECK(logger_);
    logger_.reset();
  }

  // Allocates a unique id for a new channel. Never returns 0.
  static uint32_t AllocateChannelId() { return ++last_allocated_channel_id_; }

  // Logs the creation of a channel.
  static void LogChannelCreation(uint32_t channel_id,
                                 const char* channel_type_name) {
    if (!logger_) {
      return;
    }

    logger_->LogChannelCreation(GetTimeTicksNow(), channel_id,
                                channel_type_name);
  }

  // Logs a channel message.
  static void LogChannelMessage(uint32_t channel_id, Message* message) {
    if (!logger_) {
      return;
    }

    Array<uint8_t> array = Array<uint8_t>::New(message->data_num_bytes());
    memcpy(array.data(), message->data(), message->data_num_bytes());
    logger_->LogChannelMessage(GetTimeTicksNow(), channel_id, array.Pass());
  }

  // Logs the deletion of a channel.
  static void LogChannelDeletion(uint32_t channel_id) {
    if (!logger_) {
      return;
    }

    logger_->LogChannelDeletion(GetTimeTicksNow(), channel_id);
  }

 private:
  static std::atomic_ulong last_allocated_channel_id_;
  static FlogLoggerPtr logger_;
};

// Channel backing a FlogProxy.
class FlogChannel : public MessageReceiverWithResponder {
 public:
  FlogChannel(const char* channel_type_name);

  ~FlogChannel() override;

  // Returns the channel id.
  uint32_t id() const { return id_; }

  // MessageReceiverWithResponder implementation.
  bool Accept(Message* message) override;

  bool AcceptWithResponder(Message* message,
                           MessageReceiver* responder) override;

 private:
  uint32_t id_ = 0;
};

template <typename T>
class FlogProxy : public T::Proxy_ {
 public:
  static std::unique_ptr<FlogProxy<T>> Create() {
    return std::unique_ptr<FlogProxy<T>>(new FlogProxy<T>());
  }

  FlogChannel* channel() {
    return reinterpret_cast<FlogChannel*>(this->receiver_);
  }

 private:
  explicit FlogProxy() : T::Proxy_(new FlogChannel(T::Name_)) {}
};

}  // namespace flog
}  // namespace mojo

#endif  // MOJO_SERVICES_FLOG_CPP_FLOG_H_
