// Copyright 2016 Google Inc. All Rights Reserved.
//
// 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 "cobalt/network/net_log_logger.h"

#include <stdio.h>

#include <limits>
#include <string>

#include "base/bind.h"
#include "base/file_util.h"
#include "base/json/json_writer.h"
#include "base/logging.h"
#include "base/memory/scoped_ptr.h"
#include "base/threading/thread_restrictions.h"
#include "base/time.h"
#include "base/values.h"
#include "cobalt/network/net_log_constants.h"

namespace cobalt {
namespace network {
namespace {
base::PlatformFile OpenFile(const FilePath& log_path) {
  int creation_flags =
      base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE;
  return base::CreatePlatformFile(log_path, creation_flags, NULL /* created */,
                                  NULL /* error */);
}

void AppendToFile(base::PlatformFile file, const std::string& data) {
  DCHECK_LE(data.size(), static_cast<size_t>(std::numeric_limits<int>::max()));
  int num_bytes_to_write = static_cast<int>(data.size());
  int bytes_written = base::WritePlatformFileAtCurrentPos(file, data.c_str(),
                                                          num_bytes_to_write);
  UNREFERENCED_PARAMETER(bytes_written);
  DLOG_IF(FATAL, bytes_written != num_bytes_to_write)
      << "Did not write all bytes to file.";
}

void CloseFile(base::PlatformFile file) {
  bool success = base::ClosePlatformFile(file);
  UNREFERENCED_PARAMETER(success);
  DLOG_IF(ERROR, !success) << "Failed to close file.";
}
}  // namespace

NetLogLogger::NetLogLogger(const FilePath& log_path)
    : log_writer_thread_("NetLogLogger IO"),
      log_file_(base::kInvalidPlatformFileValue) {
  if (!log_path.empty()) {
    base::ThreadRestrictions::ScopedAllowIO allow_io;
    log_file_ = OpenFile(log_path);
    if (log_file_ == base::kInvalidPlatformFileValue) {
      LOG(ERROR) << "Could not open file " << log_path.value()
                 << " for net logging";
      return;
    }

    const int kDefaultStackSize = 0;
    log_writer_thread_.StartWithOptions(
        base::Thread::Options(MessageLoop::TYPE_IO, kDefaultStackSize));

    // Write constants to the output file.  This allows loading files that have
    // different source and event types, as they may be added and removed
    // between Chrome versions.
    scoped_ptr<Value> value(NetLogConstants::GetConstants());
    std::string json;
    base::JSONWriter::Write(value.get(), &json);
    WriteToLog("{\"constants\": ");
    WriteToLog(json);
    WriteToLog(",\n");
    WriteToLog("\"events\": [\n");
  }
}

NetLogLogger::~NetLogLogger() {
  if (log_file_ != base::kInvalidPlatformFileValue) {
    log_writer_thread_.message_loop()->PostTask(
        FROM_HERE, base::Bind(&CloseFile, log_file_));
  }
  log_writer_thread_.Stop();
}

void NetLogLogger::StartObserving(net::NetLog* net_log) {
  net_log->AddThreadSafeObserver(this, net::NetLog::LOG_ALL_BUT_BYTES);
}

void NetLogLogger::OnAddEntry(const net::NetLog::Entry& entry) {
  scoped_ptr<Value> value(entry.ToValue());
  // Don't pretty print, so each JSON value occupies a single line, with no
  // breaks (Line breaks in any text field will be escaped).  Using strings
  // instead of integer identifiers allows logs from older versions to be
  // loaded, though a little extra parsing has to be done when loading a log.
  std::string json;
  base::JSONWriter::Write(value.get(), &json);
  if (log_file_ == base::kInvalidPlatformFileValue) {
    VLOG(1) << json;
  } else {
    WriteToLog(json);
    WriteToLog(",\n");
  }
}

void NetLogLogger::WriteToLog(const std::string& data) {
  DCHECK_NE(log_file_, base::kInvalidPlatformFileValue);
  DCHECK(log_writer_thread_.IsRunning());
  log_writer_thread_.message_loop()->PostTask(
      FROM_HERE, base::Bind(&AppendToFile, log_file_, data));
}

}  // namespace network
}  // namespace cobalt
