// Copyright 2016 The Weave 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 "src/access_revocation_manager_impl.h"

#include <base/json/json_reader.h>
#include <base/json/json_writer.h>
#include <base/values.h>

#include "src/commands/schema_constants.h"
#include "src/data_encoding.h"
#include "src/utils.h"

namespace weave {

namespace {
const char kConfigFileName[] = "black_list";

const char kUser[] = "user";
const char kApp[] = "app";
const char kExpiration[] = "expiration";
const char kRevocation[] = "revocation";
}

AccessRevocationManagerImpl::AccessRevocationManagerImpl(
    provider::ConfigStore* store,
    size_t capacity,
    base::Clock* clock)
    : capacity_{capacity}, clock_{clock}, store_{store} {
  Load();
}

void AccessRevocationManagerImpl::Load() {
  if (!store_)
    return;
  if (auto list = base::ListValue::From(
          base::JSONReader::Read(store_->LoadSettings(kConfigFileName)))) {
    for (const auto& value : *list) {
      const base::DictionaryValue* entry{nullptr};
      std::string user;
      std::string app;
      Entry e;
      int revocation = 0;
      int expiration = 0;
      if (value->GetAsDictionary(&entry) && entry->GetString(kUser, &user) &&
          Base64Decode(user, &e.user_id) && entry->GetString(kApp, &app) &&
          Base64Decode(app, &e.app_id) &&
          entry->GetInteger(kRevocation, &revocation) &&
          entry->GetInteger(kExpiration, &expiration)) {
        e.revocation = FromJ2000Time(revocation);
        e.expiration = FromJ2000Time(expiration);
        if (e.expiration > clock_->Now())
          entries_.insert(e);
      }
    }
    if (entries_.size() < list->GetSize()) {
      // Save some storage space by saving without expired entries.
      Save({});
    }
  }
}

void AccessRevocationManagerImpl::Save(const DoneCallback& callback) {
  if (!store_) {
    if (!callback.is_null())
      callback.Run(nullptr);
    return;
  }

  base::ListValue list;
  for (const auto& e : entries_) {
    scoped_ptr<base::DictionaryValue> entry{new base::DictionaryValue};
    entry->SetString(kUser, Base64Encode(e.user_id));
    entry->SetString(kApp, Base64Encode(e.app_id));
    entry->SetInteger(kRevocation, ToJ2000Time(e.revocation));
    entry->SetInteger(kExpiration, ToJ2000Time(e.expiration));
    list.Append(std::move(entry));
  }

  std::string json;
  base::JSONWriter::Write(list, &json);
  store_->SaveSettings(kConfigFileName, json, callback);
}

void AccessRevocationManagerImpl::RemoveExpired() {
  for (auto i = begin(entries_); i != end(entries_);) {
    if (i->expiration <= clock_->Now())
      i = entries_.erase(i);
    else
      ++i;
  }
}

void AccessRevocationManagerImpl::AddEntryAddedCallback(
    const base::Closure& callback) {
  on_entry_added_callbacks_.push_back(callback);
}

void AccessRevocationManagerImpl::Block(const Entry& entry,
                                        const DoneCallback& callback) {
  // Iterating is OK as Save below is more expensive.
  RemoveExpired();
  if (entry.expiration <= clock_->Now()) {
    if (!callback.is_null()) {
      ErrorPtr error;
      Error::AddTo(&error, FROM_HERE, "aleady_expired",
                   "Entry already expired");
      callback.Run(std::move(error));
    }
    return;
  }
  if (entries_.size() >= capacity_) {
    if (!callback.is_null()) {
      ErrorPtr error;
      Error::AddTo(&error, FROM_HERE, "blacklist_is_full",
                   "Unable to store more entries");
      callback.Run(std::move(error));
    }
    return;
  }

  auto existing = entries_.find(entry);
  if (existing != entries_.end()) {
    Entry new_entry = entry;
    new_entry.expiration = std::max(entry.expiration, existing->expiration);
    new_entry.revocation = std::max(entry.revocation, existing->revocation);
    entries_.erase(existing);
    entries_.insert(new_entry);
  } else {
    entries_.insert(entry);
  }

  for (const auto& cb : on_entry_added_callbacks_)
    cb.Run();

  Save(callback);
}

bool AccessRevocationManagerImpl::IsBlocked(const std::vector<uint8_t>& user_id,
                                            const std::vector<uint8_t>& app_id,
                                            base::Time timestamp) const {
  Entry entry_to_find;
  for (const auto& user : {{}, user_id}) {
    for (const auto& app : {{}, app_id}) {
      entry_to_find.user_id = user;
      entry_to_find.app_id = app;
      auto match = entries_.find(entry_to_find);
      if (match != end(entries_) && match->expiration > clock_->Now() &&
          match->revocation >= timestamp) {
        return true;
      }
    }
  }
  return false;
}

std::vector<AccessRevocationManager::Entry>
AccessRevocationManagerImpl::GetEntries() const {
  return {begin(entries_), end(entries_)};
}

size_t AccessRevocationManagerImpl::GetSize() const {
  return entries_.size();
}

size_t AccessRevocationManagerImpl::GetCapacity() const {
  return capacity_;
}

}  // namespace weave
