// Copyright (c) 2013 The Chromium 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 "chromeos/network/network_profile_handler.h"

#include <stddef.h>

#include <algorithm>

#include "base/bind.h"
#include "base/strings/string_util.h"
#include "base/values.h"
#include "chromeos/dbus/dbus_thread_manager.h"
#include "chromeos/dbus/shill_manager_client.h"
#include "chromeos/dbus/shill_profile_client.h"
#include "chromeos/network/network_profile_observer.h"
#include "dbus/object_path.h"
#include "third_party/cros_system_api/dbus/service_constants.h"

namespace chromeos {

namespace {

bool ConvertListValueToStringVector(const base::ListValue& string_list,
                                    std::vector<std::string>* result) {
  for (size_t i = 0; i < string_list.GetSize(); ++i) {
    std::string str;
    if (!string_list.GetString(i, &str))
      return false;
    result->push_back(str);
  }
  return true;
}

void LogProfileRequestError(const std::string& profile_path,
                            const std::string& error_name,
                            const std::string& error_message) {
  LOG(ERROR) << "Error when requesting properties for profile "
             << profile_path << ": " << error_message;
}

class ProfilePathEquals {
 public:
  explicit ProfilePathEquals(const std::string& path)
      : path_(path) {
  }

  bool operator()(const NetworkProfile& profile) {
    return profile.path == path_;
  }

 private:
  std::string path_;
};

}  // namespace

// static
std::string NetworkProfileHandler::GetSharedProfilePath() {
  return ShillProfileClient::GetSharedProfilePath();
}

void NetworkProfileHandler::AddObserver(NetworkProfileObserver* observer) {
  observers_.AddObserver(observer);
}

void NetworkProfileHandler::RemoveObserver(NetworkProfileObserver* observer) {
  observers_.RemoveObserver(observer);
}

void NetworkProfileHandler::GetManagerPropertiesCallback(
    DBusMethodCallStatus call_status,
    const base::DictionaryValue& properties) {
  if (DBUS_METHOD_CALL_FAILURE) {
    LOG(ERROR) << "Error when requesting manager properties.";
    return;
  }

  const base::Value* profiles = NULL;
  properties.GetWithoutPathExpansion(shill::kProfilesProperty, &profiles);
  if (!profiles) {
    LOG(ERROR) << "Manager properties returned from Shill don't contain "
               << "the field " << shill::kProfilesProperty;
    return;
  }
  OnPropertyChanged(shill::kProfilesProperty, *profiles);
}

void NetworkProfileHandler::OnPropertyChanged(const std::string& name,
                                              const base::Value& value) {
  if (name != shill::kProfilesProperty)
    return;

  const base::ListValue* profiles_value = NULL;
  value.GetAsList(&profiles_value);
  DCHECK(profiles_value);

  std::vector<std::string> new_profile_paths;
  bool result = ConvertListValueToStringVector(*profiles_value,
                                               &new_profile_paths);
  DCHECK(result);

  VLOG(2) << "Profiles: " << profiles_.size();
  // Search for removed profiles.
  std::vector<std::string> removed_profile_paths;
  for (ProfileList::const_iterator it = profiles_.begin();
       it != profiles_.end(); ++it) {
    if (std::find(new_profile_paths.begin(),
                  new_profile_paths.end(),
                  it->path) == new_profile_paths.end()) {
      removed_profile_paths.push_back(it->path);
    }
  }

  for (const std::string& profile_path : removed_profile_paths) {
    RemoveProfile(profile_path);
    // Also stop pending creations of this profile.
    pending_profile_creations_.erase(profile_path);
  }

  for (std::vector<std::string>::const_iterator it = new_profile_paths.begin();
       it != new_profile_paths.end(); ++it) {
    // Skip known profiles. The associated userhash should never change.
    if (GetProfileForPath(*it) || pending_profile_creations_.count(*it) > 0)
      continue;
    pending_profile_creations_.insert(*it);

    VLOG(2) << "Requesting properties of profile path " << *it << ".";
    DBusThreadManager::Get()->GetShillProfileClient()->GetProperties(
        dbus::ObjectPath(*it),
        base::Bind(&NetworkProfileHandler::GetProfilePropertiesCallback,
                   weak_ptr_factory_.GetWeakPtr(),
                   *it),
        base::Bind(&LogProfileRequestError, *it));
  }
}

void NetworkProfileHandler::GetProfilePropertiesCallback(
    const std::string& profile_path,
    const base::DictionaryValue& properties) {
  if (pending_profile_creations_.erase(profile_path) == 0) {
    VLOG(1) << "Ignore received properties, profile was removed.";
    return;
  }
  if (GetProfileForPath(profile_path)) {
    VLOG(1) << "Ignore received properties, profile is already created.";
    return;
  }
  std::string userhash;
  properties.GetStringWithoutPathExpansion(shill::kUserHashProperty, &userhash);

  AddProfile(NetworkProfile(profile_path, userhash));
}

void NetworkProfileHandler::AddProfile(const NetworkProfile& profile) {
  VLOG(2) << "Adding profile " << profile.ToDebugString() << ".";
  profiles_.push_back(profile);
  for (auto& observer : observers_)
    observer.OnProfileAdded(profiles_.back());
}

void NetworkProfileHandler::RemoveProfile(const std::string& profile_path) {
  VLOG(2) << "Removing profile for path " << profile_path << ".";
  ProfileList::iterator found = std::find_if(profiles_.begin(), profiles_.end(),
                                             ProfilePathEquals(profile_path));
  if (found == profiles_.end())
    return;
  NetworkProfile profile = *found;
  profiles_.erase(found);
  for (auto& observer : observers_)
    observer.OnProfileRemoved(profile);
}

const NetworkProfile* NetworkProfileHandler::GetProfileForPath(
    const std::string& profile_path) const {
  ProfileList::const_iterator found =
      std::find_if(profiles_.begin(), profiles_.end(),
                   ProfilePathEquals(profile_path));

  if (found == profiles_.end())
    return NULL;
  return &*found;
}

const NetworkProfile* NetworkProfileHandler::GetProfileForUserhash(
    const std::string& userhash) const {
  for (NetworkProfileHandler::ProfileList::const_iterator it =
           profiles_.begin();
       it != profiles_.end(); ++it) {
    if (it->userhash == userhash)
      return &*it;
  }
  return NULL;
}

const NetworkProfile* NetworkProfileHandler::GetDefaultUserProfile() const {
  for (NetworkProfileHandler::ProfileList::const_iterator it =
           profiles_.begin();
       it != profiles_.end(); ++it) {
    if (!it->userhash.empty())
      return &*it;
  }
  return NULL;
}

NetworkProfileHandler::NetworkProfileHandler()
    : weak_ptr_factory_(this) {
}

void NetworkProfileHandler::Init() {
  DBusThreadManager::Get()->GetShillManagerClient()->
      AddPropertyChangedObserver(this);

  // Request the initial profile list.
  DBusThreadManager::Get()->GetShillManagerClient()->GetProperties(
      base::Bind(&NetworkProfileHandler::GetManagerPropertiesCallback,
                 weak_ptr_factory_.GetWeakPtr()));
}

NetworkProfileHandler::~NetworkProfileHandler() {
  DBusThreadManager::Get()->GetShillManagerClient()->
      RemovePropertyChangedObserver(this);
}

}  // namespace chromeos
