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

#include <vector>

#include <base/file_path.h>
#include <base/string_number_conversions.h>
#include <base/stringprintf.h>
#include <chromeos/dbus/service_constants.h>

#include "shill/adaptor_interfaces.h"
#include "shill/control_interface.h"
#include "shill/link_monitor.h"
#include "shill/manager.h"
#include "shill/portal_detector.h"
#include "shill/resolver.h"
#include "shill/store_interface.h"

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

namespace shill {
// static
const char DefaultProfile::kDefaultId[] = "default";
// static
const char DefaultProfile::kStorageId[] = "global";
// static
const char DefaultProfile::kStorageArpGateway[] = "ArpGateway";
// static
const char DefaultProfile::kStorageCheckPortalList[] = "CheckPortalList";
// static
const char DefaultProfile::kStorageHostName[] = "HostName";
// static
const char DefaultProfile::kStorageLinkMonitorTechnologies[] =
    "LinkMonitorTechnologies";
// static
const char DefaultProfile::kStorageName[] = "Name";
// static
const char DefaultProfile::kStorageOfflineMode[] = "OfflineMode";
// static
const char DefaultProfile::kStoragePortalURL[] = "PortalURL";
// static
const char DefaultProfile::kStoragePortalCheckInterval[] =
    "PortalCheckInterval";
// static
const char DefaultProfile::kStorageShortDNSTimeoutTechnologies[] =
    "ShortDNSTimeoutTechnologies";

DefaultProfile::DefaultProfile(ControlInterface *control,
                               Manager *manager,
                               const FilePath &storage_path,
                               const string &profile_id,
                               const Manager::Properties &manager_props)
    : Profile(control, manager, Identifier(profile_id), "", true),
      storage_path_(storage_path),
      profile_id_(profile_id),
      props_(manager_props) {
  PropertyStore *store = this->mutable_store();
  store->RegisterConstBool(flimflam::kArpGatewayProperty,
                           &manager_props.arp_gateway);
  store->RegisterConstString(flimflam::kCheckPortalListProperty,
                             &manager_props.check_portal_list);
  store->RegisterConstString(flimflam::kCountryProperty,
                             &manager_props.country);
  store->RegisterConstString(shill::kLinkMonitorTechnologiesProperty,
                             &manager_props.link_monitor_technologies);
  store->RegisterConstBool(flimflam::kOfflineModeProperty,
                           &manager_props.offline_mode);
  store->RegisterConstString(flimflam::kPortalURLProperty,
                             &manager_props.portal_url);
  store->RegisterConstInt32(shill::kPortalCheckIntervalProperty,
                            &manager_props.portal_check_interval_seconds);
  store->RegisterConstString(shill::kShortDNSTimeoutTechnologiesProperty,
                             &manager_props.short_dns_timeout_technologies);
}

DefaultProfile::~DefaultProfile() {}

bool DefaultProfile::LoadManagerProperties(Manager::Properties *manager_props) {
  storage()->GetBool(kStorageId, kStorageArpGateway,
                     &manager_props->arp_gateway);
  storage()->GetString(kStorageId, kStorageHostName, &manager_props->host_name);
  storage()->GetBool(kStorageId, kStorageOfflineMode,
                     &manager_props->offline_mode);
  if (!storage()->GetString(kStorageId,
                            kStorageCheckPortalList,
                            &manager_props->check_portal_list)) {
    manager_props->check_portal_list = PortalDetector::kDefaultCheckPortalList;
  }
  if (!storage()->GetString(kStorageId,
                            kStorageLinkMonitorTechnologies,
                            &manager_props->link_monitor_technologies)) {
    manager_props->link_monitor_technologies =
        LinkMonitor::kDefaultLinkMonitorTechnologies;
  }
  if (!storage()->GetString(kStorageId, kStoragePortalURL,
                            &manager_props->portal_url)) {
    manager_props->portal_url = PortalDetector::kDefaultURL;
  }
  std::string check_interval;
  if (!storage()->GetString(kStorageId, kStoragePortalCheckInterval,
                            &check_interval) ||
      !base::StringToInt(check_interval,
                         &manager_props->portal_check_interval_seconds)) {
    manager_props->portal_check_interval_seconds =
        PortalDetector::kDefaultCheckIntervalSeconds;
  }
  if (!storage()->GetString(kStorageId,
                            kStorageShortDNSTimeoutTechnologies,
                            &manager_props->short_dns_timeout_technologies)) {
    manager_props->short_dns_timeout_technologies =
        Resolver::kDefaultShortTimeoutTechnologies;
  }
  return true;
}

bool DefaultProfile::ConfigureService(const ServiceRefPtr &service) {
  if (Profile::ConfigureService(service)) {
    return true;
  }
  if (service->technology() == Technology::kEthernet) {
    // Ethernet services should have an affinity towards the default profile,
    // so even if a new Ethernet service has no known configuration, accept
    // it anyway.
    UpdateService(service);
    service->set_profile(this);
    return true;
  }
  return false;
}

bool DefaultProfile::Save() {
  storage()->SetBool(kStorageId, kStorageArpGateway, props_.arp_gateway);
  storage()->SetString(kStorageId, kStorageHostName, props_.host_name);
  storage()->SetString(kStorageId, kStorageName, GetFriendlyName());
  storage()->SetBool(kStorageId, kStorageOfflineMode, props_.offline_mode);
  storage()->SetString(kStorageId,
                       kStorageCheckPortalList,
                       props_.check_portal_list);
  storage()->SetString(kStorageId,
                       kStorageLinkMonitorTechnologies,
                       props_.link_monitor_technologies);
  storage()->SetString(kStorageId,
                       kStoragePortalURL,
                       props_.portal_url);
  storage()->SetString(kStorageId,
                       kStoragePortalCheckInterval,
                       base::IntToString(props_.portal_check_interval_seconds));
  storage()->SetString(kStorageId,
                       kStorageShortDNSTimeoutTechnologies,
                       props_.short_dns_timeout_technologies);
  return Profile::Save();
}

bool DefaultProfile::UpdateDevice(const DeviceRefPtr &device) {
  return device->Save(storage()) && storage()->Flush();
}

bool DefaultProfile::GetStoragePath(FilePath *path) {
  *path = storage_path_.Append(base::StringPrintf("%s.profile",
                                                  profile_id_.c_str()));
  return true;
}

}  // namespace shill
