// Copyright (c) 2010 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 "entd/entd.h"

#include <stdio.h>

#include <iostream>

#include <base/file_util.h>
#include <event.h>
#include <glib-object.h>
#include <v8.h>

#include "cros/chromeos_cros_api.h"
#include "entd/browser.h"
#include "entd/callback_server.h"
#include "entd/flimflam.h"
#include "entd/http.h"
#include "entd/crypto_openssl.h"
#include "entd/crypto_pkcs11.h"
#include "entd/scriptable.h"
#include "entd/syslog.h"
#include "entd/tpm.h"
#include "entd/utils.h"

namespace entd {

using std::string;
static const char* kOpenSSLConfigName = "entd";

void dispatch_OnTimeout(int fd, short flags, void* arg);

// Class to represent a pending timeout event.
class Timeout {
 public:
  Timeout()
      : entd_(NULL), event_(NULL) {
  }

  virtual ~Timeout() {
    v8_value_.Dispose();
    delete event_;
  }

  virtual bool Initialize(Entd* entd, v8::Handle<v8::Value> v8_value,
                          uint32_t interval) {
    entd_ = entd;
    v8_value_ = v8::Persistent<v8::Value>::New(v8_value);

    // Least significant half (on 32bit x86 :P) of the address of the timeout
    // data, shifted left 16 bytes and or'd with the timeout sequence
    // should give us unique timeout handles that are difficult to guess.
    handle_ = (((0xFFFF & reinterpret_cast<size_t>(this)) << 16) |
               ++Timeout::sequence);

    struct timeval tv = { 0, interval * 1000 };
    event_ = new struct event;
    event_set(event_, 0, 0, &dispatch_OnTimeout, this);
    event_add(event_, &tv);

    return true;
  }

  virtual uint32_t GetHandle() const {
    return handle_;
  }

  virtual v8::Local<v8::Value> GetValue() const {
    return v8::Local<v8::Value>::New(v8_value_);
  }

  virtual Entd* GetEntd() const {
    return entd_;
  }

  virtual void CancelEvent() {
    event_del(event_);
  }

 private:
  // Count of timeouts created so far, used to ensure globally unique handles.
  static uint32_t sequence;

  // Pointer to the daemon instance.
  Entd* entd_;
  // Integer handle used to identify this timeout to JavaScript.
  uint32_t handle_;
  // JS value to execute when the timeout fires.
  v8::Persistent<v8::Value> v8_value_;
  // libevent structure for this timeout event.
  struct event* event_;

  DISALLOW_COPY_AND_ASSIGN(Timeout);
};

uint32_t Timeout::sequence = 0;

// Class to handle calling native timeouts. Implemented using libevent.
class NativeTimeout
{
 public:
  NativeTimeout(Entd::NativeTimeoutCallback cb, void* data,
                uint32_t interval_ms)
      : callback_(cb), data_(data),
        interval_(interval_ms * 1000),
        handle_(0), event_(NULL) {
  }

  ~NativeTimeout() {
    event_del(event_);
    delete event_;
  }

  void Initialize() {
    handle_ = s_handle_counter_++;
    event_ = new struct event;
    event_set(event_, 0, 0, &EventCallback, this);
    Start();
  }

  // Calling Start on a running timeout will simply reset the timer
  void Start() {
    struct timeval tv = { 0, interval_ };
    event_add(event_, &tv);
  }

  uint32_t GetHandle() { return handle_; }

 private:
  // Calls the set callback. If the callback returns 'true', start it again.
  static void EventCallback(int fd, short flags, void* arg) {
    NativeTimeout* timeout = reinterpret_cast<NativeTimeout*>(arg);
    bool res = timeout->callback_(timeout->data_);
    if (res) {
      timeout->Start();
    }
  }

  // Callback data
  Entd::NativeTimeoutCallback callback_;
  void* data_;

  uint32_t interval_;

  // Handle identifier (simple integer incrementing from 1)
  uint32_t handle_;

  // libevent data
  struct event* event_;

  // Global handle counter
  static uint32_t s_handle_counter_;

  DISALLOW_COPY_AND_ASSIGN(NativeTimeout);
};

uint32_t NativeTimeout::s_handle_counter_ = 1;

// Called by libevent when a signal is detected.
void dispatch_OnSignal(int fd, short flags, void* arg) {
  Entd* entd = reinterpret_cast<Entd*>(arg);
  entd->OnSignal(fd);
}

// Called by libevent when a timeout fires.
void dispatch_OnTimeout(int fd, short flags, void* arg) {
  Timeout* timeout = reinterpret_cast<Timeout*>(arg);
  // LOG(INFO) << "Fire timeout: " << timeout->GetHandle();
  timeout->GetEntd()->OnTimeout(*timeout);
  delete timeout;
}

// Called by v8 for entd.setTimeout().
v8::Handle<v8::Value> dispatch_SetTimeout(const v8::Arguments& args) {
  Entd* entd = Entd::Unwrap(args.This());
  if (!entd)
    return v8::Undefined();

  if (args.Length() < 2) {
    ThrowException(v8::String::New("Not enough parameters"));
    return v8::Undefined();
  }

  if (!(args[0]->IsString() || args[0]->IsFunction())) {
    ThrowException(v8::String::New(
        "First argument must be string or function"));
    return v8::Undefined();
  }

  return v8::Uint32::New(entd->SetTimeout(args[0], args[1]->Uint32Value()));
}

// Called by v8 for entd.clearTimeout().
v8::Handle<v8::Value> dispatch_ClearTimeout(const v8::Arguments& args) {
  Entd* entd = Entd::Unwrap(args.This());
  if (!entd)
    return v8::Undefined();

  if (args.Length() < 1) {
    ThrowException(v8::String::New("Not enough parameters"));
    return v8::Undefined();
  }

  Timeout* timeout = entd->ClearTimeout(args[0]->Uint32Value());
  if (!timeout)
    return v8::False();

  delete timeout;
  return v8::True();
}

// Called by v8 for entd.scheduleShutdown().
v8::Handle<v8::Value> dispatch_ScheduleShutdown(const v8::Arguments& args) {
  Entd* entd = Entd::Unwrap(args.This());
  if (!entd)
    return v8::Undefined();

  uint32_t code = 0;
  if (args.Length() > 0)
    code = args[0]->Uint32Value();

  uint32_t interval = 0;
  if (args.Length() > 1)
    interval = args[1]->Uint32Value();

  entd->ScheduleShutdown(code, interval);

  return v8::True();
}

// Called by v8 when someone trys to read from entd.hostname
v8::Handle<v8::Value> dispatch_GetHostname(v8::Local<v8::String> name,
                                           const v8::AccessorInfo& info) {
  Entd* entd = Entd::Unwrap(info.Holder());
  return v8::String::New(entd->GetHostname().c_str());
}

// Called by v8 when someone trys to assign to entd.hostname
void dispatch_SetHostname(v8::Local<v8::String> name,
                          v8::Local<v8::Value> value,
                          const v8::AccessorInfo& info) {
  Entd* entd = Entd::Unwrap(info.Holder());
  if (!entd->SetHostname(*v8::String::Utf8Value(value)))
    utils::ThrowV8Exception("Invalid hostname");
}

// Called by v8 for the global object's print() method.
v8::Handle<v8::Value> dispatch_Print(const v8::Arguments& args) {
  for (int i = 0; i < args.Length(); ++i) {
    v8::Handle<v8::Value> arg = args[i];
    v8::String::Utf8Value value(arg);
    std::cout << *value;
  }

  std::cout.flush();
  return v8::Undefined();
}

// Called by v8 for the global object's print() method.
v8::Handle<v8::Value> dispatch_PrintLn(const v8::Arguments& args) {
  for (int i = 0; i < args.Length(); ++i) {
    v8::Handle<v8::Value> arg = args[i];
    v8::String::Utf8Value value(arg);
    std::cout << *value;
  }
  std::cout << "\n";
  std::cout.flush();
  return v8::Undefined();
}

// Called by v8 for the global object's readFromFile() method.
v8::Handle<v8::Value> dispatch_ReadFromFile(const v8::Arguments& args) {
  if (args.Length() != 1) {
    utils::ThrowV8Exception("Missing argument: filePath");
    return v8::False();
  }
  std::string file = utils::ValueAsUtf8String(args[0]);
  FilePath filepath = FilePath(file);
  std::string filestr;
  v8::Handle<v8::String> result;
  if (file_util::ReadFileToString(filepath, &filestr))
    result = v8::String::New(filestr.c_str(), filestr.size());
  if (result.IsEmpty())
    utils::ThrowV8Exception(std::string("Unable to read file: ") + file);
  return result;
}

// Called by v8 for the global object's writeToFile() method.
v8::Handle<v8::Value> dispatch_WriteToFile(const v8::Arguments& args) {
  if (args.Length() != 2) {
    utils::ThrowV8Exception("Insufficient arguments.");
    return v8::False();
  }
  std::string s = utils::ValueAsUtf8String(args[0]);
  std::string file = utils::ValueAsUtf8String(args[1]);
  int slen = s.length();
  int res = -1;
  if (slen > 0) {
    res = file_util::WriteFile(FilePath(file), s.c_str(), slen);
  }
  if (res < 0 || res != slen) {
    utils::ThrowV8Exception(std::string("Unable to write file: ") + file);
    return v8::False();
  }
  return v8::True();
}

// Called by v8 for the global object's GC() method.
v8::Handle<v8::Value> dispatch_GC(const v8::Arguments& args) {
  v8::V8::LowMemoryNotification();
  return v8::Undefined();
}

Entd::Entd()
    : callback_server_(NULL),
      flimflam_(new Flimflam()),
      syslog_(new Syslog()) {
  ::g_type_init();
}

Entd::~Entd() {
  // Clean up any pending timeouts.
  for (unsigned int i = 0; i < timeout_list_.size(); ++i) {
    Timeout* timeout = timeout_list_[i];
    timeout->CancelEvent();
    delete timeout;
  }
  CleanupTemplate();
  context_.Dispose();
}

bool Entd::allow_dirty_exit = false;
bool Entd::allow_file_io = false;
bool Entd::libcros_loaded = false;
std::string Entd::libcros_location = "/opt/google/chrome/chromeos/libcros.so";

// Bind "setTimeout" and "clearTimeout" to the entd template object.
void Entd::SetTemplateBindings(v8::Handle<v8::ObjectTemplate> template_object) {
  template_object->Set(v8::String::NewSymbol("setTimeout"),
                       v8::FunctionTemplate::New(dispatch_SetTimeout),
                       v8::ReadOnly);
  template_object->Set(v8::String::NewSymbol("clearTimeout"),
                       v8::FunctionTemplate::New(dispatch_ClearTimeout),
                       v8::ReadOnly);
  template_object->Set(v8::String::NewSymbol("scheduleShutdown"),
                       v8::FunctionTemplate::New(dispatch_ScheduleShutdown),
                       v8::ReadOnly);

  template_object->SetAccessor(v8::String::NewSymbol("hostname"),
                               dispatch_GetHostname,
                               dispatch_SetHostname);
}

bool Entd::Initialize() {
  if (!context_.IsEmpty()) {
    LOG(ERROR) << "Entd initialized twice.";
    return false;
  }

  event_init();
  LOG(INFO) << "Initialized libevent " << event_get_version();

  std::string errmsg;
  Entd::libcros_loaded = chromeos::LoadLibcros(
      Entd::libcros_location.c_str(), errmsg);
  if (!Entd::libcros_loaded)
    LOG(WARNING) << "Problem loading chromeos shared object: " << errmsg;

  return true;
}

v8::Handle<v8::Object> Entd::ConstructEntd() {
  v8::HandleScope handle_scope;

  // Build the entd object.
  if (!JSObjectWrapper<Entd>::Initialize()) {
    LOG(ERROR) << "Error initializing entd";
    exit(1);
  }
  v8::Handle<v8::Object> entd = obj();

  entd->Set(v8::String::NewSymbol("isLibcrosLoaded"),
            v8::Boolean::New(Entd::libcros_loaded));

  // Build the flimflam object.
  if (!flimflam_->Initialize()) {
    LOG(ERROR) << "Error initializing entd.flimflam";
    exit(1);
  }
  entd->Set(v8::String::NewSymbol("flimflam"),
            flimflam_->obj(), v8::ReadOnly);

  // Build the http object.
  Http::Reference http = Http::New();
  if (http.IsEmpty() || !http->Initialize(this, NULL)) {
    LOG(ERROR) << "Error initializing entd.http";
    exit(1);
  }
  entd->Set(v8::String::NewSymbol("http"),
            http.js_object(), v8::ReadOnly);

  // Build the syslog object.
  if (!syslog_->Initialize()) {
    LOG(ERROR) << "Error initializing entd.syslog";
    exit(1);
  }
  entd->Set(v8::String::NewSymbol("syslog"),
            syslog_->obj(), v8::ReadOnly);

  // Build the callbackServer object.
  callback_server_.reset(new CallbackServer(this));
  if (!callback_server_->Initialize()) {
    LOG(ERROR) << "Error initializing entd.callback_server";
    exit(1);
  }
  entd->Set(v8::String::NewSymbol("callbackServer"),
            callback_server_->obj(), v8::ReadOnly);

  // Build the entd.crypto object.
  v8::Handle<v8::Object> crypto_obj = v8::Object::New();
  entd->Set(v8::String::NewSymbol("crypto"), crypto_obj);

  // Hook up the entd.crypto.Pkcs11 constructor.
  crypto_obj->Set(v8::String::NewSymbol("Pkcs11"),
                  crypto::Pkcs11::constructor_template()->GetFunction());

  // Hook up the entd.crypto.OpenSSL constructor.
  crypto_obj->Set(v8::String::NewSymbol("OpenSSL"),
                  crypto::OpenSSL::constructor_template()->GetFunction());

  Browser::Reference browser = Browser::New();
  if (!browser->Initialize(this)) {
    LOG(ERROR) << "Error initializing entd.browser";
    exit(1);
  }

  entd->Set(v8::String::NewSymbol("Browser"),
            Browser::constructor_template()->GetFunction());
  entd->Set(v8::String::NewSymbol("browser"), browser->js_object());

  Tpm::Reference tpm = Tpm::New();
  if (!tpm->Initialize()) {
    LOG(ERROR) << "Error initializing entd.tpm";
    exit(1);
  }

  entd->Set(v8::String::NewSymbol("Tpm"),
            Tpm::constructor_template()->GetFunction());
  entd->Set(v8::String::NewSymbol("tpm"), tpm->js_object());

  return handle_scope.Close(entd);
}

bool Entd::StartScriptingEnvironment() {
  v8::HandleScope handle_scope;

  // Create the global object.
  v8::Handle<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
  global_template->Set(v8::String::NewSymbol("print"),
                       v8::FunctionTemplate::New(dispatch_Print),
                       v8::ReadOnly);
  global_template->Set(v8::String::NewSymbol("println"),
                       v8::FunctionTemplate::New(dispatch_PrintLn),
                       v8::ReadOnly);
  global_template->Set(v8::String::NewSymbol("GC"),
                       v8::FunctionTemplate::New(dispatch_GC),
                       v8::ReadOnly);

  if (allow_file_io) {
    global_template->Set(v8::String::NewSymbol("readFromFile"),
                         v8::FunctionTemplate::New(dispatch_ReadFromFile),
                         v8::ReadOnly);
    global_template->Set(v8::String::NewSymbol("writeToFile"),
                         v8::FunctionTemplate::New(dispatch_WriteToFile),
                         v8::ReadOnly);
  }
  context_ = v8::Context::New(NULL, global_template);

  v8::Context::Scope context_scope(context_);

  v8::Handle<v8::Object> global = context_->Global();

  // Construct the global entd object.
  v8::Handle<v8::Object> entd = ConstructEntd();

  // Set the "entd" property of the global object.
  global->Set(v8::String::NewSymbol("entd"), entd, v8::ReadOnly);

  // Temporary storage for the generic values used below.
  v8::Handle<v8::Value> value;

  // Set entd.username and entd.hostname.
  entd->Set(v8::String::NewSymbol("username"),
            v8::String::New(username_.c_str()), v8::ReadOnly);

  size_t at_pos = username_.find("@");
  if (at_pos == std::string::npos || at_pos == username_.length() - 1) {
    LOG(ERROR) << "Can't determine hostname from username: " << username_;
    return false;
  }

  if (!SetHostname(username_.substr(at_pos + 1))) {
    LOG(ERROR) << "Unable to set host name.";
    return false;
  }

  // Load manifest file, if one was provided.
  v8::Handle<v8::Object> manifest;

  if (manifest_filename_.empty()) {
    LOG(WARNING) << "No manifest file.";
  } else {
    if (!JsonParseFromFile(manifest_filename_, &value) || !value->IsObject()) {
      LOG(ERROR) << "Error loading manifest file: " << manifest_filename_;
      return false;
    }

    manifest = v8::Handle<v8::Object>::Cast(value);
  }

  // Load utility file, if one was provided.
  if (!utility_filename_.empty()) {
    LOG(INFO) << "Executing utility file: " << utility_filename_;
    if (!ExecuteFile(utility_filename_, &value)) {
      LOG(ERROR) << "Error in utility file.";
      return false;
    }

    if (entd->Has(v8::String::NewSymbol("verifyManifest"))) {
      v8::TryCatch try_catch;

      v8::Handle<v8::Value> arg;
      if (manifest.IsEmpty()) {
        arg = v8::Null();
      } else {
        arg = manifest;
      }

      value = utils::CallV8Function(entd, "verifyManifest", 1, &arg);
      if (try_catch.HasCaught()) {
        // Failed due to V8 exception
        utils::ReportV8Exception(&try_catch);
        return false;
      } else if (value.IsEmpty()) {
        // Failed for other reasons
        return false;
      }

      if (!value->IsBoolean() || value->BooleanValue() != true) {
        LOG(ERROR) << "Utility file vetoed the extension manifest.";
        return false;
      }
    }
  }

  // Load the policy file.
  if (policy_filename_.empty()) {
    LOG(ERROR) << "No policy file.";
    return false;
  }

  if (!ExecuteFile(policy_filename_, &value)) {
    LOG(ERROR) << "Error in policy file.";
    return false;
  }

  LOG(INFO) << "Policy loaded.";

  if (!crypto::OpenSSL::StaticInitialize(kOpenSSLConfigName)) {
    LOG(ERROR) << "Failed to initialize OpenSSL.";
    return false;
  }

  // Fire the onLoad event.
  if (entd->Has(v8::String::NewSymbol("onLoad"))) {
    v8::TryCatch try_catch;

    v8::Handle<v8::Value> arg;
    if (manifest.IsEmpty()) {
      arg = v8::Null();
    } else {
      arg = manifest;
    }

    value = utils::CallV8Function(entd, "onLoad", 1, &arg);
    if (try_catch.HasCaught()) {
      // Failed due to V8 exception
      utils::ReportV8Exception(&try_catch);
      return false;
    } else if (value.IsEmpty()) {
      // Failed for other reasons
      LOG(INFO) << "Policy onLoad failed for mysterious reasons.";
      return false;
    }

    LOG(INFO) << "Policy onLoad complete.";
  }

  return true;
}

bool Entd::StopScriptingEnvironment() {
  // Temporary storage for the a generic value used in this function.
  v8::Handle<v8::Value> value;

  value = context_->Global()->Get(v8::String::NewSymbol("entd"));
  if (value.IsEmpty() || !value->IsObject()) {
    LOG(ERROR) << "Global entd missing or not an object";
    return false;
  }

  v8::Handle<v8::Object> entd = v8::Handle<v8::Object>::Cast(value);

  if (entd->Has(v8::String::NewSymbol("onUnload"))) {
    v8::TryCatch try_catch;

    value = utils::CallV8Function(entd, "onUnload", 0, NULL);
    if (try_catch.HasCaught()) {
      // Failed due to V8 exception
      utils::ReportV8Exception(&try_catch);
      return false;
    } else if (value.IsEmpty()) {
      // Failed for other reasons
      return false;
    }
  }

  crypto::Pkcs11::Finalize();

  // Unload OpenSSL modules.
  crypto::OpenSSL::StaticFinalize();

  return true;
}

// static
bool Entd::LibcrosLoadedOrThrow() {
  if (!Entd::libcros_loaded) {
    utils::ThrowV8Exception("Library not loaded: libcros");
    return false;
  }

  return true;
}

// See comments in main.cc about the return values.
uint32_t Entd::Run() {
  exit_code_ = 0;

  if (!StartScriptingEnvironment())
    return 1;

  struct event ev_SIGHUP;
  struct event ev_SIGINT;
  struct event ev_SIGTERM;

  if (!Entd::allow_dirty_exit) {
    event_set(&ev_SIGHUP, SIGHUP, EV_SIGNAL | EV_PERSIST, &dispatch_OnSignal,
              reinterpret_cast<void*>(this));
    event_add(&ev_SIGHUP, NULL);
    event_set(&ev_SIGINT, SIGINT, EV_SIGNAL | EV_PERSIST, &dispatch_OnSignal,
              reinterpret_cast<void*>(this));
    event_add(&ev_SIGINT, NULL);
    event_set(&ev_SIGTERM, SIGTERM, EV_SIGNAL | EV_PERSIST, &dispatch_OnSignal,
              reinterpret_cast<void*>(this));
    event_add(&ev_SIGTERM, NULL);
  }

  // Set up the handle and context scope for JavaScript run from event handlers,
  // or from StopScriptingEnvironment().
  v8::HandleScope handle_scope;
  v8::Context::Scope context_scope(context_);

  event_loop(0);

  if (!Entd::allow_dirty_exit) {
    event_del(&ev_SIGHUP);
    event_del(&ev_SIGINT);
    event_del(&ev_SIGTERM);
  }

  if (!StopScriptingEnvironment()) {
    if (exit_code_ == 2) {
      // The policy was asking for a restart.  We failed to shut down for some
      // reason, but would still like to honor the restart.
      return 3;
    }

    if (exit_code_ < 2) {
      // We weren't going to restart anyway.
      return 1;
    }
  }

  return exit_code_;
}

void Entd::OnSignal(int signal) {
  LOG(INFO) << "Responding to signal: " << signal;
  event_loopbreak();
}

uint32_t Entd::SetTimeout(v8::Handle<v8::Value> value, uint32_t interval) {
  Timeout* timeout = new Timeout();
  if (!timeout->Initialize(this, value, interval))
    return 0;

  timeout_list_.push_back(timeout);
  return timeout->GetHandle();
}

Timeout* Entd::ClearTimeout(uint32_t timeout_handle) {
  for (unsigned int i = 0; i < timeout_list_.size(); ++i) {
    Timeout* timeout = timeout_list_[i];
    if (timeout->GetHandle() == timeout_handle) {
      // LOG(INFO) << "Remove timeout handle: " << timeout_handle;
      timeout->CancelEvent();
      timeout_list_.erase(timeout_list_.begin() + i);
      return timeout;
    }
  }

  return NULL;
}

void Entd::ScheduleShutdown(uint32_t code, uint32_t interval) {
  exit_code_ = code;
  struct timeval tv = { 0, interval * 1000 };
  event_loopexit(&tv);
}

void Entd::OnTimeout(const Timeout& timeout) {
  v8::Context::Scope context_scope(context_);
  v8::HandleScope handle_scope;

  uint32_t timeout_handle = timeout.GetHandle();
  // LOG(INFO) << "OnTimeout: " << timeout_handle;

  // Remove this from our active timeouts list first, so any attempt to
  // call clearTimeout from script doesn't cause trouble.  If we can't clear
  // the timeout for some reason then something strange is going on.  A
  // timeout should only get removed from the list of timeouts by firing
  // (this case) or through a ClearTimeout, which should prevent it from
  // firing.
  if (!ClearTimeout(timeout_handle))
    LOG(ERROR) << "Failed to clear the current timeout, something is fishy.";

  v8::Local<v8::Value> value = timeout.GetValue();
  if (value->IsString()) {
    v8::Handle<v8::String> script = v8::Handle<v8::String>::Cast(value);
    v8::Handle<v8::Value> result;
    char filename[20];
    snprintf(&filename[0], sizeof(filename), "(timeout %u)", timeout_handle);
    ExecuteString(script, filename, &result);

  } else if (value->IsFunction()) {
    v8::Handle<v8::Function> func = v8::Handle<v8::Function>::Cast(value);
    func->Call(context_->Global(), 0, NULL);
  }
}

// Initialize and start a timeout
uint32_t Entd::SetNativeTimeout(NativeTimeoutCallback cb, void* data,
                                uint32_t interval_ms) {
  NativeTimeout* timeout = new NativeTimeout(cb, data, interval_ms);
  uint32_t handle = timeout->GetHandle();
  native_timeouts_[handle] = timeout;
  timeout->Initialize();
  return handle;
}

// Start an existing timeout (resets timer if already started)
// Returns false if timeout doesn't exist
bool Entd::StartNativeTimeout(uint32_t handle) {
  std::map<uint32_t, NativeTimeout*>::iterator iter =
      native_timeouts_.find(handle);
  if (iter != native_timeouts_.end()) {
    iter->second->Start();
    return true;
  }
  return false;
}

// Cancel and delete an existing timeout
// Returns false if timeout doesn't exist
bool Entd::ClearNativeTimeout(uint32_t handle) {
  std::map<uint32_t, NativeTimeout*>::iterator iter =
      native_timeouts_.find(handle);
  if (iter != native_timeouts_.end()) {
    delete iter->second;
    native_timeouts_.erase(iter);
    return true;
  }
  return false;
}

bool Entd::CheckHostname(const string& new_hostname) {
  if (hostname_.empty())
    return utils::CheckHostnameCharset(new_hostname);

  size_t new_len = new_hostname.length();
  size_t current_len = hostname_.length();

  if (new_len < current_len) {
    // New hostname is shorter than the existing hostname, can't possibly
    // be right.
    return false;
  }

  size_t starts_at = new_len - current_len;

  if (new_hostname.compare(starts_at, current_len, hostname_) != 0) {
    // New host doesn't match existing one.
    return false;
  }

  if (starts_at == 0) {
    // New host and old host are exactly the same.
    return true;
  }

  // Otherwise, the new hostname must more specific than the existing one.

  if (starts_at < 2) {
    // It takes at least two characters to be more specific (eg: add "a." to
    // the existing hostname.)
    return false;
  }

  if (new_hostname[starts_at - 1] != '.')
    return false;

  return utils::CheckHostnameCharset(new_hostname);
}

bool Entd::JsonParseFromFile(const string& filename,
                             v8::Handle<v8::Value>* result) {
  if (!result) {
    LOG(ERROR) << "Null pointer passed for result";
    return false;
  }

  v8::Handle<v8::String> source = utils::ReadFile(filename);
  if (source.IsEmpty()) {
    LOG(ERROR) << "Error reading json file: " << filename;
    return false;
  }

  return JsonParse(source, result);
}

bool Entd::JsonParse(v8::Handle<v8::String> source,
                     v8::Handle<v8::Value>* result) {
  return CallJson("parse", source, result);
}

bool Entd::JsonStringify(v8::Handle<v8::Value> source,
                         v8::Handle<v8::Value>* result) {
  return CallJson("stringify", source, result);
}

bool Entd::CallJson(string method_name, v8::Handle<v8::Value> arg,
                    v8::Handle<v8::Value>* result) {
  if (!result) {
    LOG(ERROR) << "Null pointer passed for result";
    return false;
  }

  v8::Handle<v8::Value> value =
      context_->Global()->Get(v8::String::NewSymbol("JSON"));
  if (value.IsEmpty() || !value->IsObject()) {
    LOG(ERROR) << "Global JSON property missing or not an object.";
    return false;
  }

  v8::Handle<v8::Object> json = v8::Handle<v8::Object>::Cast(value);

  value = json->Get(v8::String::NewSymbol(method_name.c_str()));
  if (value.IsEmpty() || !value->IsFunction()) {
    LOG(ERROR) << "JSON method missing or not a function: " << method_name;
    return false;
  }

  v8::Handle<v8::Function> fun = v8::Handle<v8::Function>::Cast(value);

  v8::TryCatch try_catch;
  v8::Handle<v8::Value> call_result =
      utils::CallV8Function(json, method_name, 1, &arg);
  if (try_catch.HasCaught()) {
    // Failed due to V8 exception
    utils::ReportV8Exception(&try_catch);
    return false;
  } else if (call_result.IsEmpty()) {
    // Failed for other reasons
    return false;
  }

  *result = call_result;

  return true;
}

bool Entd::ExecuteFile(const std::string& filename,
                       v8::Handle<v8::Value>* result) {
  v8::HandleScope handle_scope;
  v8::Handle<v8::String> source = utils::ReadFile(filename);
  if (source.IsEmpty()) {
    PLOG(WARNING) << "Error reading source file: " << filename;
    return false;
  }

  return ExecuteString(source, filename, result);
}

bool Entd::ExecuteString(const v8::Handle<v8::String>& source,
                         const std::string& filename,
                         v8::Handle<v8::Value>* result) {
  v8::HandleScope handle_scope;
  v8::TryCatch try_catch;

  v8::Handle<v8::Script> script =
      v8::Script::Compile(source, v8::String::New(filename.c_str()));

  if (script.IsEmpty()) {
    utils::ReportV8Exception(&try_catch);
    return false;
  }

  *result = script->Run();
  if (!result || result->IsEmpty()) {
    utils::ReportV8Exception(&try_catch);
    return false;
  }

  return true;
}

}  // namespace entd
