// 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 "shill/wimax.h"

#include <string>

#include <base/bind.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>

#include "shill/key_value_store.h"
#include "shill/logging.h"
#include "shill/manager.h"
#include "shill/proxy_factory.h"
#include "shill/wimax_device_proxy_interface.h"
#include "shill/wimax_service.h"

using base::Bind;
using std::set;
using std::string;

namespace shill {

namespace {

const char *DeviceStatusToString(wimax_manager::DeviceStatus status) {
  switch (status) {
    case wimax_manager::kDeviceStatusUninitialized:
      return "Uninitialized";
    case wimax_manager::kDeviceStatusDisabled:
      return "Disabled";
    case wimax_manager::kDeviceStatusReady:
      return "Ready";
    case wimax_manager::kDeviceStatusScanning:
      return "Scanning";
    case wimax_manager::kDeviceStatusConnecting:
      return "Connecting";
    case wimax_manager::kDeviceStatusConnected:
      return "Connected";
    default:
      return "Unknown";
  }
}

}  // namespace

const int WiMax::kDefaultConnectTimeoutSeconds = 60;
const int WiMax::kDefaultRPCTimeoutSeconds = 30;

WiMax::WiMax(ControlInterface *control,
             EventDispatcher *dispatcher,
             Metrics *metrics,
             Manager *manager,
             const string &link_name,
             const string &address,
             int interface_index,
             const RpcIdentifier &path)
    : Device(control, dispatcher, metrics, manager, link_name, address,
             interface_index, Technology::kWiMax),
      path_(path),
      weak_ptr_factory_(this),
      scanning_(false),
      status_(wimax_manager::kDeviceStatusUninitialized),
      proxy_factory_(ProxyFactory::GetInstance()),
      connect_timeout_seconds_(kDefaultConnectTimeoutSeconds) {
  LOG(INFO) << "WiMAX device created: " << link_name << " @ " << path;
  PropertyStore *store = mutable_store();
  store->RegisterConstBool(kScanningProperty, &scanning_);
}

WiMax::~WiMax() {
  LOG(INFO) << "WiMAX device destroyed: " << link_name();
}

void WiMax::Start(Error *error, const EnabledStateChangedCallback &callback) {
  SLOG(WiMax, 2) << __func__;
  scanning_ = false;
  proxy_.reset(proxy_factory_->CreateWiMaxDeviceProxy(path_));
  proxy_->set_networks_changed_callback(
      Bind(&WiMax::OnNetworksChanged, Unretained(this)));
  proxy_->set_status_changed_callback(
      Bind(&WiMax::OnStatusChanged, Unretained(this)));
  proxy_->Enable(
      error, Bind(&WiMax::OnEnableComplete, this, callback),
      kDefaultRPCTimeoutSeconds * 1000);
}

void WiMax::Stop(Error *error, const EnabledStateChangedCallback &callback) {
  SLOG(WiMax, 2) << __func__;
  StopConnectTimeout();
  if (pending_service_) {
    pending_service_->SetState(Service::kStateIdle);
    pending_service_ = nullptr;
  }
  if (selected_service()) {
    Error error;
    DisconnectFrom(selected_service(), &error);
  }
  scanning_ = false;
  networks_.clear();
  manager()->wimax_provider()->OnNetworksChanged();
  if (proxy_.get()) {
    proxy_->Disable(
        error, Bind(&WiMax::OnDisableComplete, this, callback),
        kDefaultRPCTimeoutSeconds * 1000);
  } else {
    OnDisableComplete(callback, Error());
  }
}

void WiMax::Scan(ScanType /*scan_type*/, Error *error,
                 const string &/*reason*/) {
  SLOG(WiMax, 2) << __func__;
  if (scanning_) {
    Error::PopulateAndLog(
        error, Error::kInProgress, "Scan already in progress.");
    return;
  }
  scanning_ = true;
  proxy_->ScanNetworks(
      error, Bind(&WiMax::OnScanNetworksComplete, this),
      kDefaultRPCTimeoutSeconds * 1000);
  if (error->IsFailure()) {
    OnScanNetworksComplete(*error);
  }
}

void WiMax::ConnectTo(const WiMaxServiceRefPtr &service, Error *error) {
  SLOG(WiMax, 2) << __func__ << "(" << service->GetStorageIdentifier() << ")";
  if (pending_service_) {
    Error::PopulateAndLog(
        error, Error::kInProgress,
        base::StringPrintf(
            "Pending connect to service %s, ignoring connect request to %s.",
            pending_service_->unique_name().c_str(),
            service->GetStorageIdentifier().c_str()));
    return;
  }
  service->SetState(Service::kStateAssociating);
  pending_service_ = service;

  // We use the RPC device status to determine the outcome of the connect
  // operation by listening for status updates in OnStatusChanged. A transition
  // to Connected means success. A transition to Connecting and then to a status
  // different than Connected means failure. Also, schedule a connect timeout to
  // guard against the RPC device never transitioning to a Connecting or a
  // Connected state.
  status_ = wimax_manager::kDeviceStatusUninitialized;
  StartConnectTimeout();

  KeyValueStore parameters;
  service->GetConnectParameters(&parameters);
  proxy_->Connect(
      service->GetNetworkObjectPath(), parameters,
      error, Bind(&WiMax::OnConnectComplete, this),
      kDefaultRPCTimeoutSeconds * 1000);
  if (error->IsFailure()) {
    OnConnectComplete(*error);
  }
}

void WiMax::DisconnectFrom(const ServiceRefPtr &service, Error *error) {
  SLOG(WiMax, 2) << __func__;
  if (pending_service_) {
    Error::PopulateAndLog(
        error, Error::kInProgress,
        base::StringPrintf(
            "Pending connect to service %s, "
            "ignoring disconnect request from %s.",
            pending_service_->unique_name().c_str(),
            service->GetStorageIdentifier().c_str()));
    return;
  }
  if (selected_service() && service != selected_service()) {
    Error::PopulateAndLog(
        error, Error::kNotConnected,
        base::StringPrintf(
            "Current service is %s, ignoring disconnect request from %s.",
            selected_service()->unique_name().c_str(),
            service->GetStorageIdentifier().c_str()));
    return;
  }
  DropConnection();
  proxy_->Disconnect(
      error, Bind(&WiMax::OnDisconnectComplete, this),
      kDefaultRPCTimeoutSeconds * 1000);
  if (error->IsFailure()) {
    OnDisconnectComplete(*error);
  }
}

bool WiMax::IsIdle() const {
  return !pending_service_ && !selected_service();
}

void WiMax::OnServiceStopped(const WiMaxServiceRefPtr &service) {
  SLOG(WiMax, 2) << __func__;
  if (service == selected_service()) {
    DropConnection();
  }
  if (service == pending_service_) {
    pending_service_ = nullptr;
  }
}

void WiMax::OnDeviceVanished() {
  LOG(INFO) << "WiMAX device vanished: " << link_name();
  proxy_.reset();
  DropService(Service::kStateIdle);
  // Disable the device. This will also clear any relevant properties such as
  // the live network set.
  SetEnabled(false);
}

void WiMax::OnScanNetworksComplete(const Error &/*error*/) {
  SLOG(WiMax, 2) << __func__;
  scanning_ = false;
  // The networks are updated when the NetworksChanged signal is received.
}

void WiMax::OnConnectComplete(const Error &error) {
  SLOG(WiMax, 2) << __func__;
  if (error.IsSuccess()) {
    // Nothing to do -- the connection process is resumed on the StatusChanged
    // signal.
    return;
  }
  DropService(Service::kStateFailure);
}

void WiMax::OnDisconnectComplete(const Error &/*error*/) {
  SLOG(WiMax, 2) << __func__;
}

void WiMax::OnEnableComplete(const EnabledStateChangedCallback &callback,
                             const Error &error) {
  SLOG(WiMax, 2) << __func__;
  if (error.IsFailure()) {
    proxy_.reset();
  } else {
    LOG(INFO) << "WiMAX device " << link_name() << " enabled.";
    // Updates the live networks based on the current WiMaxManager.Device
    // networks. The RPC device will signal when the network set changes.
    Error e;
    OnNetworksChanged(proxy_->Networks(&e));
  }
  callback.Run(error);
}

void WiMax::OnDisableComplete(const EnabledStateChangedCallback &callback,
                              const Error &error) {
  LOG(INFO) << "WiMAX device " << link_name() << " disabled.";
  proxy_.reset();
  callback.Run(error);
}

void WiMax::OnNetworksChanged(const RpcIdentifiers &networks) {
  SLOG(WiMax, 2) << __func__;
  networks_.clear();
  networks_.insert(networks.begin(), networks.end());
  manager()->wimax_provider()->OnNetworksChanged();
}

void WiMax::OnStatusChanged(wimax_manager::DeviceStatus status) {
  SLOG(WiMax, 2) << "WiMAX device " << link_name()
                 << " status: " << DeviceStatusToString(status);
  wimax_manager::DeviceStatus old_status = status_;
  status_ = status;
  switch (status) {
    case wimax_manager::kDeviceStatusConnected:
      if (!pending_service_) {
        LOG(WARNING) << "Unexpected status change; ignored.";
        return;
      }
      // Stops the connect timeout -- the DHCP provider has a separate timeout.
      StopConnectTimeout();
      if (AcquireIPConfig()) {
        LOG(INFO) << "WiMAX device " << link_name() << " connected to "
                  << pending_service_->GetStorageIdentifier();
        SelectService(pending_service_);
        pending_service_ = nullptr;
        SetServiceState(Service::kStateConfiguring);
      } else {
        DropService(Service::kStateFailure);
      }
      break;
    case wimax_manager::kDeviceStatusConnecting:
      LOG(INFO) << "WiMAX device " << link_name() << " connecting...";
      // Nothing to do.
      break;
    default:
      // We may receive a queued up status update (e.g., to Scanning) before
      // receiving the status update to Connecting, so be careful to fail the
      // service only on the right status transition.
      if (old_status == wimax_manager::kDeviceStatusConnecting ||
          old_status == wimax_manager::kDeviceStatusConnected) {
        LOG(INFO) << "WiMAX device " << link_name()
                  << " status: " << DeviceStatusToString(old_status)
                  << " -> " << DeviceStatusToString(status);
        // TODO(benchan): Investigate a method to determine if the connection
        // failure is due to incorrect EAP credentials and indicate that via
        // Service::kFailureBadPassphrase (crosbug.com/p/16324).
        DropService(Service::kStateFailure);
      }
      break;
  }
}

void WiMax::DropService(Service::ConnectState state) {
  SLOG(WiMax, 2) << __func__
                 << "(" << Service::ConnectStateToString(state) << ")";
  StopConnectTimeout();
  if (pending_service_) {
    LOG(WARNING) << "Unable to initiate connection to: "
                 << pending_service_->GetStorageIdentifier();
    pending_service_->SetState(state);
    pending_service_ = nullptr;
  }
  if (selected_service()) {
    LOG(WARNING) << "Service disconnected: "
                 << selected_service()->GetStorageIdentifier();
    selected_service()->SetState(state);
    DropConnection();
  }
}

void WiMax::StartConnectTimeout() {
  SLOG(WiMax, 2) << __func__;
  if (IsConnectTimeoutStarted()) {
    return;
  }
  connect_timeout_callback_.Reset(
      Bind(&WiMax::OnConnectTimeout, weak_ptr_factory_.GetWeakPtr()));
  dispatcher()->PostDelayedTask(
      connect_timeout_callback_.callback(), connect_timeout_seconds_ * 1000);
}

void WiMax::StopConnectTimeout() {
  SLOG(WiMax, 2) << __func__;
  connect_timeout_callback_.Cancel();
}

bool WiMax::IsConnectTimeoutStarted() const {
  return !connect_timeout_callback_.IsCancelled();
}

void WiMax::OnConnectTimeout() {
  LOG(ERROR) << "WiMAX device " << link_name() << ": connect timeout.";
  StopConnectTimeout();
  DropService(Service::kStateFailure);
}

}  // namespace shill
