// Copyright (c) 2010, 2011 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 "src/service_manager_impl.h"

#include <glog/logging.h>

#include "src/cashew_server.h"
#include "src/service.h"

namespace cashew {

// Flimflam D-Bus indentifiers
static const char *kFlimflamManagerName = "org.chromium.flimflam";
static const char *kFlimflamManagerPath = "/";

// Flimflam property names
static const char *kDefaultTechnologyProperty = "DefaultTechnology";
static const char *kServicesProperty = "Services";
static const char *kStateProperty = "State";

// Flimflam on-the-wire State values
static const char *kFlimflamStateOffline = "offline";
static const char *kFlimflamStateConnected = "connected";
static const char *kFlimflamStateOnline = "online";

// Flimflam service types
static const char *kTypeCellular = "cellular";

// GetFlimflamProperties retry interval
static const guint kSecondsPerMinute = 60;
static const guint kGetFlimflamPropertiesIntervalSeconds =
    1 * kSecondsPerMinute;

ServiceManagerImpl::ServiceManagerImpl(DBus::Connection& connection,  // NOLINT
                                       GMainLoop * const main_loop)
    : DBus::ObjectProxy(connection, kFlimflamManagerPath,
                        kFlimflamManagerName),
      connection_(connection), main_loop_(CHECK_NOTNULL(main_loop)),
      cashew_server_(NULL), default_technology_(Service::kTypeUnknown),
      default_cellular_service_(NULL),
      connectivity_state_(kConnectivityStateUnknown),
      get_properties_source_id_(0), retrying_get_properties_(false) {
  // schedule a GetProperties() call to Flimflam to init our state
  // we'll keep trying periodically until we succeed
  // we'll subsequently update this state by monitoring PropertyChanged signals
  get_properties_source_id_ =
      g_idle_add(StaticGetFlimflamPropertiesCallback, this);
  if (get_properties_source_id_ == 0) {
    LOG(ERROR) << "ctor: g_idle_add failed";
  }
  property_changed_handler_.delegate(this);
}

ServiceManagerImpl::~ServiceManagerImpl() {
  DCHECK(!g_main_loop_is_running(main_loop_));
  ClearDefaultCellularService();
  DeleteServices(&services_);
  if (get_properties_source_id_ != 0 &&
      !g_source_remove(get_properties_source_id_)) {
    DLOG(WARNING) << "dtor: g_source_remove failed";
  }
}

const Service* ServiceManagerImpl::GetService(const std::string& service_path)
    const {
  ServiceMap::const_iterator it = services_.find(service_path);
  if (it == services_.end()) {
    return NULL;
  }
  DCHECK(it->second != NULL);
  return static_cast<const Service *>(it->second);
}

void ServiceManagerImpl::SetCashewServer(CashewServer *cashew_server) {
  DLOG(INFO) << "SetCashewServer";
  cashew_server_ = cashew_server;
}

Service::Type ServiceManagerImpl::GetDefaultTechnology() const {
  return default_technology_;
}

ServiceManager::ConnectivityState ServiceManagerImpl::GetConnectivityState()
    const {
  return connectivity_state_;
}

// static
bool ServiceManagerImpl::IsOfflineConnectivityState(
    ServiceManager::ConnectivityState state) {
  if (state == kConnectivityStateUnknown ||
      state == kConnectivityStateOffline) {
    return true;
  }
  return false;
}

// static
bool ServiceManagerImpl::IsOnlineConnectivityState(
    ServiceManager::ConnectivityState state) {
  if (state == kConnectivityStateConnected ||
      state == kConnectivityStateOnline) {
    return true;
  }
  return false;
}

// Flimflam Manager D-Bus Proxy methods

void ServiceManagerImpl::PropertyChanged(const std::string& property_name,
                                         const DBus::Variant& new_value) {
  DLOG(INFO) << "PropertyChanged: property_name = " << property_name;
  // Queue a tuple representing this signal for later processing from the glib
  // main loop.  We do this to avoid libdbus-c++ deadlocks that can occur when
  // sending a dbus message from within a dbus callback like this one.
  PropertyChangedSignal signal(property_name, new_value);
  property_changed_handler_.EnqueueSignal(signal);
}

void ServiceManagerImpl::StateChanged(const std::string& new_state_string) {
  DLOG(INFO) << "StateChanged: new_state_string = " << new_state_string;
  // Queue a tuple representing this signal for later processing from the glib
  // main loop. See comments in PropertyChanged above.
  DBus::Variant new_value;
  new_value.writer().append_string(new_state_string.c_str());
  // StateChanged is a special case of PropertyChanged, so we just construct a
  // PropertyChanged signal containing the new state info
  PropertyChangedSignal signal(kStateProperty, new_value);
  property_changed_handler_.EnqueueSignal(signal);
}

// PropertyChangedDelegate methods

void ServiceManagerImpl::OnPropertyChanged(
                                          const PropertyChangedHandler *handler,
                                          const std::string& property_name,
                                          const DBus::Variant& new_value) {
  DCHECK(handler == &property_changed_handler_);
  DLOG(INFO) << "OnPropertyChanged: property_name = " << property_name;
  if (property_name == kDefaultTechnologyProperty) {
    OnDefaultTechnologyUpdate(new_value.reader().get_string());
  } else if (property_name == kServicesProperty) {
    // interpret new_value as a vector of service paths
    ServicePathList paths;
    DBus::MessageIter reader = new_value.reader();
    reader >> paths;
    OnServicesUpdate(paths);
  } else if (property_name == kStateProperty) {
    OnStateUpdate(new_value.reader().get_string());
  } else {
    // we don't care about this property
  }
}

// Service methods

void ServiceManagerImpl::EmitDataPlansUpdate(const Service& service) {
  DLOG(INFO) << "EmitDataPlansUpdate: service = " << service.GetPath();
  if (cashew_server_ == NULL) {
    DLOG(WARNING) << "EmitDataPlansUpdate: no Cashew server";
    return;
  }
  cashew_server_->EmitDataPlansUpdate(service);
}

void ServiceManagerImpl::OnDataPlanInactive(const Service& service,
                                            const DataPlan& plan) {
  DLOG(INFO) << "OnDataPlanInactive: service = " << service.GetPath()
      << ", plan = " << plan.GetName();
  DCHECK(!plan.IsActive());
  // TODO(vlaviano): hook for future use
  // we could emit a PlanExpired D-Bus signal for Chrome to consume
}

// Private methods

void ServiceManagerImpl::DeleteServices(ServiceMap *service_map) {
  DCHECK(service_map != NULL);
  while (!service_map->empty()) {
    const std::string& path =
        static_cast<std::string>(service_map->begin()->first);
    DLOG(INFO) << "DeleteServices: deleting service: " << path;
    Service *service = static_cast<Service *>(service_map->begin()->second);
    DCHECK(service != NULL);
    DCHECK(service != default_cellular_service_);
    DCHECK(*service_map == services_ || GetService(service->GetPath()) == NULL);
    delete service;
    service_map->erase(service_map->begin());
  }
}

// static
gboolean ServiceManagerImpl::StaticGetFlimflamPropertiesCallback(
                                                                gpointer data) {
  ServiceManagerImpl *service_manager =
      reinterpret_cast<ServiceManagerImpl*>(data);
  CHECK_NOTNULL(service_manager);
  DCHECK_NE(service_manager->get_properties_source_id_, 0);
  if (!service_manager->GetFlimflamProperties()) {
    // call failed, so try again later
    DLOG(WARNING) << "StaticGetFlimflamPropertiesCallback: "
        << "GetFlimflamProperties failed, will retry in "
        << kGetFlimflamPropertiesIntervalSeconds << " secs";
    // if we've arrived here from our first g_idle_add call, set up a timer
    if (!service_manager->retrying_get_properties_) {
      guint source_id =
          g_timeout_add_seconds(kGetFlimflamPropertiesIntervalSeconds,
                                StaticGetFlimflamPropertiesCallback,
                                service_manager);
      service_manager->get_properties_source_id_ = source_id;
      if (source_id == 0) {
        LOG(ERROR) << "StaticGetFlimflamPropertiesCallback: "
            << "g_timeout_add_seconds failed";
        return FALSE;  // get rid of old glib source and give up
      }
      service_manager->retrying_get_properties_ = true;
      // get rid of our old glib source, but our new timer will call us
      return FALSE;
    }
    // otherwise, our timer is already set up
    // return TRUE to indicate that we want to be called again later
    return TRUE;
  }
  service_manager->get_properties_source_id_ = 0;
  service_manager->retrying_get_properties_ = false;
  return FALSE;  // we succeeded, so don't repeat
}

bool ServiceManagerImpl::GetFlimflamProperties() {
  DLOG(INFO) << "GetFlimflamProperties";
  PropertyMap properties;
  // dbus-c++ throws exceptions
  // invoke the "Existing Non-conformant Code" clause of the style guide and
  // isolate the rest of the system from this
  try {
    // TODO(vlaviano): make this call asynchronous
    properties = GetProperties();
  } catch (DBus::Error& error) {  // NOLINT
    LOG(WARNING) << "GetFlimflamProperties: GetProperties() -> Exception: "
        << error.name() << ": " << error.message();
    return false;
  } catch (...) {  // NOLINT
    LOG(WARNING) << "GetFlimflamProperties: GetProperties() -> Exception";
    return false;
  }
  DLOG(INFO) << "GetFlimflamProperties: Received " << properties.size()
      << " properties";

  // grab the properties in which we're interested
  PropertyMap::const_iterator it = properties.find(kDefaultTechnologyProperty);
  if (it != properties.end()) {
    const DBus::Variant& value = static_cast<DBus::Variant>(it->second);
    OnDefaultTechnologyUpdate(value.reader().get_string());
  } else {
    DLOG(WARNING) << "GetFlimflamProperties: no DefaultTechnology property";
  }
  it = properties.find(kServicesProperty);
  if (it != properties.end()) {
    const DBus::Variant& value = static_cast<DBus::Variant>(it->second);
    // interpret value as vector of service paths
    ServicePathList paths;
    DBus::MessageIter reader = value.reader();
    reader >> paths;
    OnServicesUpdate(paths);
  } else {
    DLOG(WARNING) << "GetFlimflamProperties: no Services property";
  }
  it = properties.find(kStateProperty);
  if (it != properties.end()) {
    const DBus::Variant& value = static_cast<DBus::Variant>(it->second);
    StateChanged(value.reader().get_string());
  } else {
    DLOG(WARNING) << "GetFlimflamProperties: no State property";
  }
  return true;
}

void ServiceManagerImpl::OnStateUpdate(const std::string& new_state_string) {
  DLOG(INFO) << "OnStateUpdate: new_state = " << new_state_string;
  ConnectivityState old_state = connectivity_state_;
  connectivity_state_ = ConnectivityStateFromString(new_state_string);
  // see if we're coming online or going offline
  // NOTE: we consider "unknown" to be offline
  if (IsOfflineConnectivityState(old_state) &&
      IsOnlineConnectivityState(connectivity_state_)) {
    OnFlimflamOnline();
  } else if (IsOnlineConnectivityState(old_state) &&
      IsOfflineConnectivityState(connectivity_state_)) {
    OnFlimflamOffline();
  }
}

void ServiceManagerImpl::OnDefaultTechnologyUpdate(
    const std::string& default_technology) {
  DLOG(INFO) << "OnDefaultTechnologyUpdate: default technology = "
      << default_technology;
  default_technology_ = Service::TypeFromString(default_technology);
  if (default_technology_ == Service::kTypeUnknown) {
    LOG(WARNING) << "OnDefaultTechnologyUpdate: unknown default technology: "
        << default_technology;
  }
  if (default_technology_ != Service::kTypeCellular &&
      default_cellular_service_ != NULL) {
    // if the default technology isn't cellular and yet we think that one of
    // our cellular services is the default service, then we need to update
    // our view of the world.
    ClearDefaultCellularService();
  }
}

void ServiceManagerImpl::OnServicesUpdate(const ServicePathList& paths) {
  // Remember old set of services. This is the baseline from which we will
  // determine what has changed.
  ServiceMap old_services = services_;
  services_.clear();

  // Flimflam service types are embedded in their path names, so we can use
  // the pattern "/cellular_" to decide which paths are cellular services.
  static const std::string cellular_pattern = std::string("/") + kTypeCellular
      + "_";

  // Walk paths in this update and see if they're new to us
  DLOG(INFO) << "OnServicesUpdate: " << paths.size() << " service paths";
  ServicePathList::const_iterator it;
  for (it = paths.begin(); it != paths.end(); ++it) {
    const DBus::Path& path = *it;

    // We only care about cellular services
    if (path.find(cellular_pattern) == std::string::npos) {
      continue;
    }

    ServiceMap::iterator old_it = old_services.find(path);
    if (old_it != old_services.end()) {
      // service is old: move it from old_services to services_
      Service *service = static_cast<Service *>(old_it->second);
      DCHECK(service != NULL);
      old_services.erase(old_it);
      services_[path] = service;
    } else {
      // service is new: create a Service obj for it and add it to services_
      OnNewService(path);
    }
  }

  // clear default service if it failed to appear in the update and we're
  // about to delete it
  if (default_cellular_service_ != NULL) {
    ServiceMap::const_iterator it =
        old_services.find(default_cellular_service_->GetPath());
    if (it != old_services.end()) {
      ClearDefaultCellularService();
    }
  }

  // services left in old_services failed to appear in the update: delete them
  DeleteServices(&old_services);

  // Flimflam always places the default service first in its list of services,
  // so we'll take a look at the first element in the paths list and see if the
  // default service has changed. Note that |paths| can be empty. We still want
  // to know about this, since it means that there is no default service.
  const DBus::Path *default_service_path = NULL;
  if (!paths.empty()) {
    default_service_path = &*paths.begin();
  }
  OnDefaultServiceUpdate(default_service_path);
}

void ServiceManagerImpl::OnNewService(const DBus::Path& path) {
  DLOG(INFO) << "OnNewService: " << path;
  DCHECK(GetService(path) == NULL);
  Service *service = Service::NewService(this, connection_, path);
  if (service == NULL) {
    LOG(ERROR) << "OnNewService: couldn't create service for " << path;
    return;
  }
  services_[path] = service;
}

void ServiceManagerImpl::OnDefaultServiceUpdate(const DBus::Path *path) {
  DLOG(INFO) << "OnDefaultServiceUpdate: new default service = "
      << ((path == NULL) ? "None" : *path);
  // check if new default service path (if any) corresponds to one of our
  // cellular services
  Service *new_default_cellular_service = NULL;
  if (path != NULL) {
    new_default_cellular_service = const_cast<Service*>(GetService(*path));
  }
  if (new_default_cellular_service != NULL) {
    SetDefaultCellularService(new_default_cellular_service);
  } else {
    ClearDefaultCellularService();
  }
}

void ServiceManagerImpl::ClearDefaultCellularService() {
  DLOG(INFO) << "ClearDefaultCellularService";
  if (default_cellular_service_ != NULL) {
    DCHECK(default_cellular_service_->IsDefaultService());
    default_cellular_service_->OnDefaultServiceUpdate(false);
    default_cellular_service_ = NULL;
  }
}

void ServiceManagerImpl::SetDefaultCellularService(Service *service) {
  DLOG(INFO) << "SetDefaultCellularService: "
      << ((service == NULL) ? "None" : service->GetPath());
  if (default_cellular_service_ == service) {
    return;
  }
  if (default_cellular_service_ != NULL) {
    ClearDefaultCellularService();
  }
  DCHECK(default_cellular_service_ == NULL);
  if (service != NULL) {
    DCHECK(!service->IsDefaultService());
    service->OnDefaultServiceUpdate(true);
    default_cellular_service_ = service;
  }
}

// static
ServiceManager::ConnectivityState
ServiceManagerImpl::ConnectivityStateFromString(const std::string& state) {
  if (state == kFlimflamStateOffline) {
    return kConnectivityStateOffline;
  }
  if (state == kFlimflamStateConnected) {
    return kConnectivityStateConnected;
  }
  if (state == kFlimflamStateOnline) {
    return kConnectivityStateOnline;
  }
  return kConnectivityStateUnknown;
}

void ServiceManagerImpl::OnFlimflamOnline() {
  DLOG(INFO) << "OnFlimflamOnline";
  // notify our child services
  ServiceMap::iterator it;
  for (it = services_.begin(); it != services_.end(); ++it) {
    Service *service = static_cast<Service*>(it->second);
    DCHECK(service != NULL);
    service->OnFlimflamOnline();
  }
}

void ServiceManagerImpl::OnFlimflamOffline() {
  DLOG(INFO) << "OnFlimflamOffline";
  // notify our child services
  ServiceMap::iterator it;
  for (it = services_.begin(); it != services_.end(); ++it) {
    Service *service = static_cast<Service*>(it->second);
    DCHECK(service != NULL);
    service->OnFlimflamOffline();
  }
}

}  // namespace cashew
