// Copyright (c) 2012 The Chromium OS 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 <signal.h>
#include <stdio.h>
#include <sys/signalfd.h>
#include <sys/types.h>
#include <unistd.h>

#include <base/command_line.h>
#include <base/logging.h>
#include <chromeos/dbus/service_constants.h>
#include <chromeos/syslog_logging.h>
#include <dbus-c++/glib-integration.h>
#include <dbus-c++/util.h>

#include "cromo/carrier.h"
#include "cromo/cromo_server.h"
#include "cromo/plugin_manager.h"
#include "cromo/sandbox.h"
#include "cromo/syslog_helper.h"

#ifndef VCSID
#define VCSID "<not set>"
#endif

DBus::Glib::BusDispatcher dispatcher;
GMainLoop* main_loop;
static CromoServer* server;

static const int kExitMaxTries = 10;
static int kExitTries = 0;

namespace switches {

// Comma-separated list of plugins to load at startup
static const char kPlugins[] = "plugins";
// Flag that causes shill to show the help message and exit.
static const char kHelp[] = "help";

// The help message shown if help flag is passed to the program.
static const char kHelpMessage[] = "\n"
    "Available Switches: \n"
    "  --plugins\n"
    "    comma-separated list of plugins to load at startup\n";
}  // namespace switches

// This function is run on a timer by exit_main_loop(). It calls all of the
// exit-ok hooks to see if they are all ready for the program to exit; it also
// keeps track of tries so that we time out appropriately if one of the devices
// isn't disconnecting properly.
static gboolean test_for_exit(void* arg) {
  int* tries = static_cast<int*>(arg);
  if ((*tries)++ < kExitMaxTries && !server->exit_ok_hooks().Run())
    // Event needs to be scheduled again.
    return TRUE;
  g_main_loop_quit(main_loop);
  // We're done here; exit the program.
  return FALSE;
}

// This function starts exiting the main loop. We run all the pre-exit hooks,
// then keep testing every second to see if all the exit hooks think it's okay
// to exit.
static void exit_main_loop(void) {
  server->start_exit_hooks().Run();
  if (server->exit_ok_hooks().Run()) {
    g_main_loop_quit(main_loop);
    return;
  }
  g_timeout_add_seconds(1, test_for_exit, &kExitTries);
}

static gboolean do_signal(void* arg) {
  intptr_t sig = reinterpret_cast<intptr_t>(arg);
  LOG(INFO) << "Signal: " << sig;

  if (sig == SIGTERM || sig == SIGINT) {
    exit_main_loop();
  }

  return FALSE;
}

static void* handle_signals(void* arg) {
  sigset_t sigs;
  siginfo_t info;
  info.si_signo = 0;
  sigemptyset(&sigs);
  sigaddset(&sigs, SIGTERM);
  sigaddset(&sigs, SIGINT);
  LOG(INFO) << "waiting for signals";
  while (info.si_signo != SIGTERM && info.si_signo != SIGINT) {
    sigwaitinfo(&sigs, &info);
    g_idle_add(do_signal, reinterpret_cast<void*>(info.si_signo));
  }
  return nullptr;
}

static gboolean setup_signals(void* arg) {
  pthread_t thr;
  pthread_create(&thr, nullptr, handle_signals, nullptr);
  return FALSE;
}

static void block_signals(void) {
  sigset_t sigs;

  sigemptyset(&sigs);
  sigaddset(&sigs, SIGTERM);
  sigaddset(&sigs, SIGINT);
  pthread_sigmask(SIG_BLOCK, &sigs, nullptr);
}

// Always logs to the syslog and stderr.
void SetupLogging(void) {
  int log_flags = 0;
  log_flags |= chromeos::kLogToSyslog;
  log_flags |= chromeos::kLogToStderr;
  log_flags |= chromeos::kLogHeader;
  chromeos::InitLog(log_flags);
}

int main(int argc, char* argv[]) {
  // Drop privs right away for now.
  // TODO(ellyjones): once we do more serious sandboxing, this will need to be
  // broken into two parts, one to be done pre-plugin load and one to be done
  // post-plugin load -- or we can just do the whole thing post-plugin load.
  Sandbox::Enter();

  base::CommandLine::Init(argc, argv);
  base::CommandLine* cl = base::CommandLine::ForCurrentProcess();

  if (cl->HasSwitch(switches::kHelp)) {
    LOG(INFO) << switches::kHelpMessage;
    return 0;
  }

  SysLogHelperInit();
  SetupLogging();

  block_signals();

  DBus::default_dispatcher = &dispatcher;
  dispatcher.attach(nullptr);

  DBus::Connection conn = DBus::Connection::SystemBus();

  CHECK(conn.acquire_name(CromoServer::kServiceName))
      << "Failed to acquire D-Bus name " << CromoServer::kServiceName;

  server = new CromoServer(conn);

  // Add carriers before plugins so that they can be overidden
  AddBaselineCarriers(server);

  // Instantiate modem handlers for each type of hardware supported
  std::string plugins = cl->GetSwitchValueASCII(switches::kPlugins);
  PluginManager::LoadPlugins(server, plugins);

  dispatcher.enter();
  main_loop = g_main_loop_new(nullptr, false);
  g_idle_add(setup_signals, nullptr);
  g_main_loop_run(main_loop);

  PluginManager::UnloadPlugins(false);
  LOG(INFO) << "Exit";
  return 0;
}
