// Copyright 2018 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/dhcp/dhcp_properties.h"

#include <memory>
#include <string>

#include <base/macros.h>
#include <chromeos/dbus/service_constants.h>

#include "shill/key_value_store.h"
#include "shill/logging.h"
#include "shill/property_accessor.h"
#include "shill/property_store.h"
#include "shill/store_interface.h"

using std::string;

namespace shill {

namespace Logging {
static auto kModuleLogScope = ScopeLogger::kDHCP;
static string ObjectID(const DhcpProperties* d) { return "(dhcp_properties)"; }
}

namespace {

// Prefix used for DhcpProperties in the PropertyStore.
const char kStoragePrefix[] = "DHCPProperty.";

const char* const kPropertyNames[] = {DhcpProperties::kHostnameProperty,
                                      DhcpProperties::kVendorClassProperty};

std::string GetFullPropertyName(const std::string& property_name) {
  return kStoragePrefix + property_name;
}

}  // namespace

const char DhcpProperties::kHostnameProperty[] = "Hostname";
const char DhcpProperties::kVendorClassProperty[] = "VendorClass";

DhcpProperties::DhcpProperties() {}

DhcpProperties::~DhcpProperties() {}

void DhcpProperties::InitPropertyStore(PropertyStore* store) {
  SLOG(this, 2) << __func__;
  int i = 0;
  for (const auto& name : kPropertyNames) {
    store->RegisterDerivedString(
        GetFullPropertyName(name),
        StringAccessor(
            new CustomMappedAccessor<DhcpProperties, string, size_t>(
                this,
                &DhcpProperties::ClearMappedStringProperty,
                &DhcpProperties::GetMappedStringProperty,
                &DhcpProperties::SetMappedStringProperty,
                i)));
    ++i;
  }
}

void DhcpProperties::Load(StoreInterface* storage, const string& id) {
  SLOG(this, 2) << __func__;
  properties_.Clear();
  for (const auto& name : kPropertyNames) {
    string property_value;
    if (storage->GetString(id, GetFullPropertyName(name), &property_value)) {
      properties_.SetString(name, property_value);
      SLOG(this, 3) << "found DhcpProperty: setting " << name;
    }
  }
}

void DhcpProperties::Save(StoreInterface* storage, const string& id) const {
  SLOG(this, 2) << __func__;
  for (const auto& name : kPropertyNames) {
    string property_value;
    if (properties_.Contains(name)) {
      // The property is in the property store and it may have a setting or be
      // set to an empty string.  This setting should be saved to the profile.
      property_value = properties_.GetString(name);
      storage->SetString(id, GetFullPropertyName(name), property_value);
      SLOG(this, 3) << "saved " << GetFullPropertyName(name);
    } else {
      // The property is not found and should be deleted from the property store
      // if it was there.
      storage->DeleteKey(id, GetFullPropertyName(name));
    }
  }
}

std::unique_ptr<DhcpProperties> DhcpProperties::Combine(
    const DhcpProperties& base, const DhcpProperties& to_merge) {
  SLOG(nullptr, 2) << __func__;
  auto to_return = std::make_unique<DhcpProperties>();
  to_return->properties_ = base.properties_;
  for (const auto& it : to_merge.properties_.properties()) {
    const string& name = it.first;
    const brillo::Any& value = it.second;
    to_return->properties_.Set(name, value);
  }
  return to_return;
}

bool DhcpProperties::GetValueForProperty(const string& name,
                                         string* value) const {
  if (properties_.ContainsString(name)) {
    *value = properties_.GetString(name);
    return true;
  }
  return false;
}

void DhcpProperties::ClearMappedStringProperty(const size_t& index,
                                               Error* error) {
  CHECK(index < arraysize(kPropertyNames));
  if (properties_.ContainsString(kPropertyNames[index])) {
    properties_.Remove(kPropertyNames[index]);
  } else {
    error->Populate(Error::kNotFound, "Property is not set");
  }
}

string DhcpProperties::GetMappedStringProperty(const size_t& index,
                                               Error* error) {
  CHECK(index < arraysize(kPropertyNames));
  if (properties_.ContainsString(kPropertyNames[index])) {
    return properties_.GetString(kPropertyNames[index]);
  }
  error->Populate(Error::kNotFound, "Property is not set");
  return string();
}

bool DhcpProperties::SetMappedStringProperty(
    const size_t& index, const string& value, Error* error) {
  CHECK(index < arraysize(kPropertyNames));
  if (properties_.ContainsString(kPropertyNames[index]) &&
      properties_.GetString(kPropertyNames[index]) == value) {
        return false;
  }
  properties_.SetString(kPropertyNames[index], value);
  return true;
}

}  // namespace shill
