//
// Copyright (C) 2014 The Android Open Source Project
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

#include "update_engine/update_manager/real_shill_provider.h"

#include <string>

#include <base/logging.h>
#include <base/strings/stringprintf.h>
#include <brillo/type_name_undecorate.h>
#include <shill/dbus-constants.h>
#include <shill/dbus-proxies.h>

using org::chromium::flimflam::ManagerProxyInterface;
using org::chromium::flimflam::ServiceProxyInterface;
using std::string;

namespace chromeos_update_manager {

ConnectionType RealShillProvider::ParseConnectionType(const string& type_str) {
  if (type_str == shill::kTypeEthernet) {
    return ConnectionType::kEthernet;
  } else if (type_str == shill::kTypeWifi) {
    return ConnectionType::kWifi;
  } else if (type_str == shill::kTypeWimax) {
    return ConnectionType::kWimax;
  } else if (type_str == shill::kTypeBluetooth) {
    return ConnectionType::kBluetooth;
  } else if (type_str == shill::kTypeCellular) {
    return ConnectionType::kCellular;
  }
  return ConnectionType::kUnknown;
}

ConnectionTethering RealShillProvider::ParseConnectionTethering(
    const string& tethering_str) {
  if (tethering_str == shill::kTetheringNotDetectedState) {
    return ConnectionTethering::kNotDetected;
  } else if (tethering_str == shill::kTetheringSuspectedState) {
    return ConnectionTethering::kSuspected;
  } else if (tethering_str == shill::kTetheringConfirmedState) {
    return ConnectionTethering::kConfirmed;
  }
  return ConnectionTethering::kUnknown;
}

bool RealShillProvider::Init() {
  ManagerProxyInterface* manager_proxy = shill_proxy_->GetManagerProxy();
  if (!manager_proxy)
    return false;

  // Subscribe to the manager's PropertyChanged signal.
  manager_proxy->RegisterPropertyChangedSignalHandler(
      base::Bind(&RealShillProvider::OnManagerPropertyChanged,
                 base::Unretained(this)),
      base::Bind(&RealShillProvider::OnSignalConnected,
                 base::Unretained(this)));

  // Attempt to read initial connection status. Even if this fails because shill
  // is not responding (e.g. it is down) we'll be notified via "PropertyChanged"
  // signal as soon as it comes up, so this is not a critical step.
  brillo::VariantDictionary properties;
  brillo::ErrorPtr error;
  if (!manager_proxy->GetProperties(&properties, &error))
    return true;

  const auto& prop_default_service =
      properties.find(shill::kDefaultServiceProperty);
  if (prop_default_service != properties.end()) {
    OnManagerPropertyChanged(prop_default_service->first,
                             prop_default_service->second);
  }

  return true;
}

void RealShillProvider::OnManagerPropertyChanged(const string& name,
                                                 const brillo::Any& value) {
  if (name == shill::kDefaultServiceProperty) {
    dbus::ObjectPath service_path = value.TryGet<dbus::ObjectPath>();
    if (!service_path.IsValid()) {
      LOG(WARNING) << "Got an invalid DefaultService path. The property value "
                      "contains a "
                   << value.GetUndecoratedTypeName()
                   << ", read as the object path: '" << service_path.value()
                   << "'";
    }
    ProcessDefaultService(service_path);
  }
}

void RealShillProvider::OnSignalConnected(const string& interface_name,
                                          const string& signal_name,
                                          bool successful) {
  if (!successful) {
    LOG(ERROR) << "Couldn't connect to the signal " << interface_name << "."
               << signal_name;
  }
}

bool RealShillProvider::ProcessDefaultService(
    const dbus::ObjectPath& default_service_path) {
  // We assume that if the service path didn't change, then the connection
  // type and the tethering status of it also didn't change.
  if (default_service_path_ == default_service_path)
    return true;

  // Update the connection status.
  default_service_path_ = default_service_path;
  bool is_connected = (default_service_path_.IsValid() &&
                       default_service_path_.value() != "/");
  var_is_connected_.SetValue(is_connected);
  var_conn_last_changed_.SetValue(clock_->GetWallclockTime());

  if (!is_connected) {
    var_conn_type_.UnsetValue();
    var_conn_tethering_.UnsetValue();
    return true;
  }

  // We create and dispose the ServiceProxyInterface on every request.
  std::unique_ptr<ServiceProxyInterface> service =
      shill_proxy_->GetServiceForPath(default_service_path_);

  // Get the connection properties synchronously.
  brillo::VariantDictionary properties;
  brillo::ErrorPtr error;
  if (!service->GetProperties(&properties, &error)) {
    var_conn_type_.UnsetValue();
    var_conn_tethering_.UnsetValue();
    return false;
  }

  // Get the connection tethering mode.
  const auto& prop_tethering = properties.find(shill::kTetheringProperty);
  if (prop_tethering == properties.end()) {
    // Remove the value if not present on the service. This most likely means an
    // error in shill and the policy will handle it, but we will print a log
    // message as well for accessing an unused variable.
    var_conn_tethering_.UnsetValue();
    LOG(ERROR) << "Could not find connection type (service: "
               << default_service_path_.value() << ")";
  } else {
    // If the property doesn't contain a string value, the empty string will
    // become kUnknown.
    var_conn_tethering_.SetValue(
        ParseConnectionTethering(prop_tethering->second.TryGet<string>()));
  }

  // Get the connection type.
  const auto& prop_type = properties.find(shill::kTypeProperty);
  if (prop_type == properties.end()) {
    var_conn_type_.UnsetValue();
    LOG(ERROR) << "Could not find connection tethering mode (service: "
               << default_service_path_.value() << ")";
  } else {
    string type_str = prop_type->second.TryGet<string>();
    if (type_str == shill::kTypeVPN) {
      const auto& prop_physical =
          properties.find(shill::kPhysicalTechnologyProperty);
      if (prop_physical == properties.end()) {
        LOG(ERROR) << "No PhysicalTechnology property found for a VPN"
                   << " connection (service: " << default_service_path_.value()
                   << "). Using default kUnknown value.";
        var_conn_type_.SetValue(ConnectionType::kUnknown);
      } else {
        var_conn_type_.SetValue(
            ParseConnectionType(prop_physical->second.TryGet<string>()));
      }
    } else {
      var_conn_type_.SetValue(ParseConnectionType(type_str));
    }
  }

  return true;
}

}  // namespace chromeos_update_manager
