// Copyright (c) 2012 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.

#include "remoting/host/host_event_logger.h"

#include <windows.h>
#include <string>
#include <vector>

#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "net/base/ip_endpoint.h"
#include "remoting/host/host_status_monitor.h"
#include "remoting/host/host_status_observer.h"
#include "remoting/protocol/transport.h"

#include "remoting_host_messages.h"

namespace remoting {

namespace {

class HostEventLoggerWin : public HostEventLogger, public HostStatusObserver {
 public:
  HostEventLoggerWin(base::WeakPtr<HostStatusMonitor> monitor,
                     const std::string& application_name);

  virtual ~HostEventLoggerWin();

  // HostStatusObserver implementation.  These methods will be called from the
  // network thread.
  virtual void OnClientAuthenticated(const std::string& jid) OVERRIDE;
  virtual void OnClientDisconnected(const std::string& jid) OVERRIDE;
  virtual void OnAccessDenied(const std::string& jid) OVERRIDE;
  virtual void OnClientRouteChange(
      const std::string& jid,
      const std::string& channel_name,
      const protocol::TransportRoute& route) OVERRIDE;
  virtual void OnStart(const std::string& xmpp_login) OVERRIDE;
  virtual void OnShutdown() OVERRIDE;

 private:
  void LogString(WORD type, DWORD event_id, const std::string& string);
  void Log(WORD type, DWORD event_id, const std::vector<std::string>& strings);

  base::WeakPtr<HostStatusMonitor> monitor_;

  // The handle of the application event log.
  HANDLE event_log_;

  DISALLOW_COPY_AND_ASSIGN(HostEventLoggerWin);
};

} //namespace

HostEventLoggerWin::HostEventLoggerWin(base::WeakPtr<HostStatusMonitor> monitor,
                                       const std::string& application_name)
    : monitor_(monitor),
      event_log_(NULL) {
  event_log_ = RegisterEventSourceW(
      NULL, base::UTF8ToUTF16(application_name).c_str());
  if (event_log_ != NULL) {
    monitor_->AddStatusObserver(this);
  } else {
    PLOG(ERROR) << "Failed to register the event source: " << application_name;
  }
}

HostEventLoggerWin::~HostEventLoggerWin() {
  if (event_log_ != NULL) {
    if (monitor_)
      monitor_->RemoveStatusObserver(this);
    DeregisterEventSource(event_log_);
  }
}

void HostEventLoggerWin::OnClientAuthenticated(const std::string& jid) {
  LogString(EVENTLOG_INFORMATION_TYPE, MSG_HOST_CLIENT_CONNECTED, jid);
}

void HostEventLoggerWin::OnClientDisconnected(const std::string& jid) {
  LogString(EVENTLOG_INFORMATION_TYPE, MSG_HOST_CLIENT_DISCONNECTED, jid);
}

void HostEventLoggerWin::OnAccessDenied(const std::string& jid) {
  LogString(EVENTLOG_ERROR_TYPE, MSG_HOST_CLIENT_ACCESS_DENIED, jid);
}

void HostEventLoggerWin::OnClientRouteChange(
    const std::string& jid,
    const std::string& channel_name,
    const protocol::TransportRoute& route) {
  std::vector<std::string> strings(5);
  strings[0] = jid;
  strings[1] = route.remote_address.ToString();
  strings[2] = route.local_address.ToString();
  strings[3] = channel_name;
  strings[4] = protocol::TransportRoute::GetTypeString(route.type);
  Log(EVENTLOG_INFORMATION_TYPE, MSG_HOST_CLIENT_ROUTING_CHANGED, strings);
}

void HostEventLoggerWin::OnShutdown() {
  // TODO(rmsousa): Fix host shutdown to actually call this, and add a log line.
}

void HostEventLoggerWin::OnStart(const std::string& xmpp_login) {
  LogString(EVENTLOG_INFORMATION_TYPE, MSG_HOST_STARTED, xmpp_login);
}

void HostEventLoggerWin::Log(WORD type,
                             DWORD event_id,
                             const std::vector<std::string>& strings) {
  if (event_log_ == NULL)
    return;

  // ReportEventW() takes an array of raw string pointers. They should stay
  // valid for the duration of the call.
  std::vector<const WCHAR*> raw_strings(strings.size());
  std::vector<base::string16> utf16_strings(strings.size());
  for (size_t i = 0; i < strings.size(); ++i) {
    utf16_strings[i] = base::UTF8ToUTF16(strings[i]);
    raw_strings[i] = utf16_strings[i].c_str();
  }

  if (!ReportEventW(event_log_,
                    type,
                    HOST_CATEGORY,
                    event_id,
                    NULL,
                    static_cast<WORD>(raw_strings.size()),
                    0,
                    &raw_strings[0],
                    NULL)) {
    PLOG(ERROR) << "Failed to write an event to the event log";
  }
}

void HostEventLoggerWin::LogString(WORD type,
                                   DWORD event_id,
                                   const std::string& string) {
  std::vector<std::string> strings;
  strings.push_back(string);
  Log(type, event_id, strings);
}

// static
scoped_ptr<HostEventLogger> HostEventLogger::Create(
    base::WeakPtr<HostStatusMonitor> monitor,
    const std::string& application_name) {
  return scoped_ptr<HostEventLogger>(
      new HostEventLoggerWin(monitor, application_name));
}

}  // namespace remoting
