// 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_black_list_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";
}

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

void AccessBlackListManagerImpl::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 AccessBlackListManagerImpl::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 AccessBlackListManagerImpl::RemoveExpired() {
  for (auto i = begin(entries_); i != end(entries_);) {
    if (i->expiration <= clock_->Now())
      i = entries_.erase(i);
    else
      ++i;
  }
}

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

void AccessBlackListManagerImpl::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 AccessBlackListManagerImpl::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<AccessBlackListManager::Entry>
AccessBlackListManagerImpl::GetEntries() const {
  return {begin(entries_), end(entries_)};
}

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

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

}  // namespace weave
