// Copyright 2015 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 "settingsd/source.h"

#include <base/logging.h>
#include <base/strings/string_split.h>
#include <string>

#include "settingsd/settings_document.h"
#include "settingsd/settings_keys.h"
#include "settingsd/settings_service.h"

namespace settingsd {

namespace {

// Setting status strings.
const char* const kSettingStatusStrings[] = {"active", "withdrawn", "invalid"};

}  // namespace

SettingStatus SettingStatusFromString(const std::string& status_string) {
  for (SettingStatus status :
       {kSettingStatusActive, kSettingStatusWithdrawn, kSettingStatusInvalid}) {
    CHECK_LT(status, sizeof(kSettingStatusStrings));
    if (status_string == kSettingStatusStrings[status])
      return status;
  }

  return kSettingStatusInvalid;
}

std::string SettingStatusToString(SettingStatus status) {
  CHECK_LT(status, sizeof(kSettingStatusStrings));
  return kSettingStatusStrings[status];
}

Key MakeSourceKey(const std::string& source_id) {
  // TODO(mnissler): Handle nested sources properly.
  return Key(keys::kSettingsdPrefix).Extend({keys::kSources, source_id});
}

Source::Source(const std::string& id)
    : id_(id), delegate_(new DummySourceDelegate()) {}

Source::~Source() {}

bool Source::CheckAccess(const SettingsDocument* document,
                         SettingStatus threshold) const {
  if (status_ > threshold)
    return false;

  const Key trust_config_area_begin(
      Key(keys::kSettingsdPrefix).Extend({keys::kSources}));
  const Key trust_config_area_end(MakeSourceKey(id_).PrefixUpperBound());

  for (auto& key : document->GetKeys(Key())) {
    if (trust_config_area_begin <= key && key < trust_config_area_end)
      return false;

    auto access_rule = FindMatchingAccessRule(key);
    if (access_rule == access_.end() || access_rule->second > threshold)
      return false;
  }

  for (auto& deletion : document->GetDeletions(Key())) {
    if ((trust_config_area_begin <= deletion &&
         deletion < trust_config_area_end) ||
        deletion.IsPrefixOf(trust_config_area_begin)) {
      return false;
    }

    auto access_rule = FindMatchingAccessRule(deletion);
    if (access_rule == access_.end() || access_rule->second > threshold)
      return false;

    // Check all access rules within the set of deleted keys.
    for (; access_rule != access_.end() &&
           deletion.IsPrefixOf(access_rule->first);
         ++access_rule) {
      if (access_rule->second > threshold)
        return false;
    }
  }

  return true;
}

bool Source::Update(
    const SourceDelegateFactoryFunction& delegate_factory_function,
    const SettingsService& settings) {
  bool has_config = false;

  name_.clear();
  BlobRef name_value =
      settings.GetValue(MakeSourceKey(id_).Extend({keys::sources::kName}));
  if (name_value.valid()) {
    has_config = true;
    name_ = name_value.ToString();
  }

  BlobRef status_value =
      settings.GetValue(MakeSourceKey(id_).Extend({keys::sources::kStatus}));
  std::string status_string;
  if (status_value.valid()) {
    has_config = true;
    status_string = status_value.ToString();
  }
  status_ = SettingStatusFromString(status_string);

  delegate_ = delegate_factory_function(id_, settings);
  has_config |= !!delegate_;
  if (!delegate_)
    delegate_.reset(new DummySourceDelegate());

  access_.clear();
  const Key access_key_prefix(
      MakeSourceKey(id_).Extend({keys::sources::kAccess}));
  const std::set<Key> access_keys(settings.GetKeys(access_key_prefix));
  for (Key access_key : access_keys) {
    has_config = true;
    status_string.clear();
    BlobRef value = settings.GetValue(access_key);
    if (value.valid())
      status_string = value.ToString();
    Key suffix;
    if (access_key.Suffix(access_key_prefix, &suffix))
      access_[suffix] = SettingStatusFromString(status_string);
    else
      NOTREACHED() << "Invalid access key " << access_key.ToString();
  }

  blob_formats_.clear();
  BlobRef formats_value = settings.GetValue(
      MakeSourceKey(id_).Extend({keys::sources::kBlobFormat}));
  if (formats_value.valid()) {
    has_config = true;
    blob_formats_ =
        base::SplitString(formats_value.ToString(), ",", base::TRIM_WHITESPACE,
                          base::SPLIT_WANT_NONEMPTY);
  }

  return has_config;
}

Source::AccessRuleMap::const_iterator Source::FindMatchingAccessRule(
    const Key& key) const {
  Key lookup_key = key;
  auto rule = access_.upper_bound(lookup_key);
  while (rule != access_.begin()) {
    --rule;
    if (rule->first.IsPrefixOf(key))
      return rule;
    lookup_key = lookup_key.CommonPrefix(rule->first);
    rule = access_.upper_bound(lookup_key);
  }

  return access_.end();
}

}  // namespace settingsd
