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

#include <algorithm>

#include <base/logging.h>
#include <base/string_util.h>
#include <chromeos/dbus/service_constants.h>

#include "shill/error.h"
#include "shill/l2tp_ipsec_driver.h"
#include "shill/manager.h"
#include "shill/openvpn_driver.h"
#include "shill/profile.h"
#include "shill/scope_logger.h"
#include "shill/store_interface.h"
#include "shill/vpn_service.h"

using std::set;
using std::string;
using std::vector;

namespace shill {

VPNProvider::VPNProvider(ControlInterface *control_interface,
                         EventDispatcher *dispatcher,
                         Metrics *metrics,
                         Manager *manager)
    : control_interface_(control_interface),
      dispatcher_(dispatcher),
      metrics_(metrics),
      manager_(manager) {}

VPNProvider::~VPNProvider() {}

void VPNProvider::Start() {}

void VPNProvider::Stop() {}

VPNServiceRefPtr VPNProvider::GetService(const KeyValueStore &args,
                                         Error *error) {
  SLOG(VPN, 2) << __func__;
  string type = args.LookupString(flimflam::kProviderTypeProperty, "");
  if (type.empty()) {
    Error::PopulateAndLog(
        error, Error::kNotSupported, "Missing VPN type property.");
    return NULL;
  }

  string storage_id = VPNService::CreateStorageIdentifier(args, error);
  if (storage_id.empty()) {
    return NULL;
  }

  // Find a service in the provider list which matches these parameters.
  VPNServiceRefPtr service = FindService(type, storage_id);

  if (service == NULL) {
    // Create a service, using the name and type arguments passed in.
    string name = args.LookupString(flimflam::kProviderNameProperty, "");
    if (name.empty()) {
      name = args.LookupString(flimflam::kNameProperty, "");
    }
    service = CreateService(type, name, storage_id, error);
  }

  if (service != NULL) {
    // Configure the service using the the rest of the passed-in arguments.
    service->Configure(args, error);
  }

  return service;
}

bool VPNProvider::OnDeviceInfoAvailable(const string &link_name,
                                        int interface_index) {
  for (vector<VPNServiceRefPtr>::const_iterator it = services_.begin();
       it != services_.end();
       ++it) {
    if ((*it)->driver()->ClaimInterface(link_name, interface_index)) {
      return true;
    }
  }

  return false;
}

void VPNProvider::RemoveService(VPNServiceRefPtr service) {
  vector<VPNServiceRefPtr>::iterator it;
  it = std::find(services_.begin(), services_.end(), service);
  if (it != services_.end()) {
    services_.erase(it);
  }
}

void VPNProvider::CreateServicesFromProfile(ProfileRefPtr profile) {
  SLOG(VPN, 2) << __func__;
  const StoreInterface *storage = profile->GetConstStorage();
  set<string> groups =
      storage->GetGroupsWithKey(flimflam::kProviderTypeProperty);
  for (set<string>::iterator it = groups.begin(); it != groups.end(); ++it) {
    if (!StartsWithASCII(*it, "vpn_", false)) {
      continue;
    }

    string type;
    if (!storage->GetString(*it, flimflam::kProviderTypeProperty, &type)) {
      LOG(ERROR) << "Group " << *it << " is missing the "
                 << flimflam::kProviderTypeProperty << " property.";
      continue;
    }

    string name;
    if (!storage->GetString(*it, flimflam::kProviderNameProperty, &name) &&
        !storage->GetString(*it, flimflam::kNameProperty, &name)) {
      LOG(ERROR) << "Group " << *it << " is missing the "
                 << flimflam::kProviderNameProperty << " property.";
      continue;
    }

    VPNServiceRefPtr service = FindService(type, *it);
    if (service != NULL) {
      // If the service already exists, it does not need to be configured,
      // since PushProfile would have already called ConfigureService on it.
      SLOG(VPN, 2) << "Service already exists " << *it;
      continue;
    }

    Error error;
    service = CreateService(type, name, *it, &error);

    if (service == NULL) {
      LOG(ERROR) << "Could not create service for " << *it;
      continue;
    }

    if (!profile->ConfigureService(service)) {
      LOG(ERROR) << "Could not configure service for " << *it;
      continue;
    }
  }
}

VPNServiceRefPtr VPNProvider::CreateService(const string &type,
                                            const string &name,
                                            const string &storage_id,
                                            Error *error) {
  SLOG(VPN, 2) << __func__ << " type " << type << " name " << name
               << " storage id " << storage_id;
  scoped_ptr<VPNDriver> driver;
  if (type == flimflam::kProviderOpenVpn) {
    driver.reset(new OpenVPNDriver(
        control_interface_, dispatcher_, metrics_, manager_,
        manager_->device_info(), manager_->glib()));
  } else if (type == flimflam::kProviderL2tpIpsec) {
    driver.reset(new L2TPIPSecDriver(
        control_interface_, dispatcher_, metrics_, manager_,
        manager_->device_info(), manager_->glib()));
  } else {
    Error::PopulateAndLog(
        error, Error::kNotSupported, "Unsupported VPN type: " + type);
    return NULL;
  }

  VPNServiceRefPtr service = new VPNService(
      control_interface_, dispatcher_, metrics_, manager_, driver.release());
  service->set_storage_id(storage_id);
  service->InitDriverPropertyStore();
  if (!name.empty()) {
    service->set_friendly_name(name);
  }
  services_.push_back(service);
  manager_->RegisterService(service);

  return service;
}

VPNServiceRefPtr VPNProvider::FindService(const std::string &type,
                                          const std::string &storage_id) {
  for (vector<VPNServiceRefPtr>::const_iterator it = services_.begin();
       it != services_.end();
       ++it) {
    if (type == (*it)->driver()->GetProviderType() &&
        storage_id == (*it)->GetStorageIdentifier()) {
      return *it;
    }
  }

  return NULL;
}

}  // namespace shill
