// Copyright 2019 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/loader/fetcher_cache.h"

#include <utility>

#include "base/bind.h"
#include "base/logging.h"
#include "base/strings/stringprintf.h"
#include "cobalt/loader/loader_types.h"

namespace cobalt {
namespace loader {
namespace {

// Wraps a Fetcher::Handler and saves all data fetched and its associated
// information.
class CachedFetcherHandler : public Fetcher::Handler {
 public:
  typedef base::Callback<void(
      const std::string& url,
      const scoped_refptr<net::HttpResponseHeaders>& headers,
      const Origin& last_url_origin, bool did_fail_from_transient_error,
      std::string data)>
      SuccessCallback;

  CachedFetcherHandler(const std::string& url, Fetcher::Handler* handler,
                       const SuccessCallback& on_success_callback)
      : url_(url),
        handler_(handler),
        on_success_callback_(on_success_callback) {
    DCHECK(handler_);
    DCHECK(!on_success_callback_.is_null());
  }

  // Attach a wrapping fetcher so it can be used when forwarding the callbacks.
  // This ensures that the underlying handler sees the same Fetcher object in
  // the callback as the one returned by CreateCachedFetcher().
  void AttachFetcher(Fetcher* wrapping_fetcher) {
    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
    DCHECK(!wrapping_fetcher_);
    DCHECK(wrapping_fetcher);

    wrapping_fetcher_ = wrapping_fetcher;
  }

 private:
  // From Fetcher::Handler.
  LoadResponseType OnResponseStarted(
      Fetcher*,
      const scoped_refptr<net::HttpResponseHeaders>& headers) override {
    // TODO: Respect HttpResponseHeaders::GetMaxAgeValue().
    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
    DCHECK(wrapping_fetcher_);

    auto response = handler_->OnResponseStarted(wrapping_fetcher_, headers);
    if (response == kLoadResponseContinue && headers) {
      headers_ = headers;
      auto content_length = headers_->GetContentLength();
      if (content_length > 0) {
        data_.reserve(static_cast<size_t>(content_length));
      }
    }
    return response;
  }

  void OnReceived(Fetcher*, const char* data, size_t size) override {
    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
    DCHECK(wrapping_fetcher_);

    data_.insert(data_.end(), data, data + size);
    handler_->OnReceived(wrapping_fetcher_, data, size);
  }

  void OnReceivedPassed(Fetcher*, std::unique_ptr<std::string> data) override {
    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
    DCHECK(wrapping_fetcher_);

    data_.insert(data_.end(), data->begin(), data->end());
    handler_->OnReceivedPassed(wrapping_fetcher_, std::move(data));
  }

  void OnDone(Fetcher*) override {
    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
    DCHECK(wrapping_fetcher_);

    handler_->OnDone(wrapping_fetcher_);
    on_success_callback_.Run(
        url_, headers_, wrapping_fetcher_->last_url_origin(),
        wrapping_fetcher_->did_fail_from_transient_error(), std::move(data_));
  }

  void OnError(Fetcher*, const std::string& error) override {
    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
    DCHECK(wrapping_fetcher_);

    handler_->OnError(wrapping_fetcher_, error);
  }

  THREAD_CHECKER(thread_checker_);

  const std::string url_;
  Fetcher* wrapping_fetcher_ = nullptr;
  Fetcher::Handler* const handler_;
  const SuccessCallback on_success_callback_;

  scoped_refptr<net::HttpResponseHeaders> headers_;
  std::string data_;
};

// Wraps an underlying, real Fetcher for an ongoing request, so we can ensure
// that |handler_| is deleted when the Fetcher object is deleted.
class OngoingFetcher : public Fetcher {
 public:
  OngoingFetcher(std::unique_ptr<CachedFetcherHandler> handler,
                 const Loader::FetcherCreator& real_fetcher_creator)
      : Fetcher(handler.get()), handler_(std::move(handler)) {
    DCHECK(handler_);
    handler_->AttachFetcher(this);
    fetcher_ = real_fetcher_creator.Run(handler_.get());
  }
  ~OngoingFetcher() override { DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); }

  Origin last_url_origin() const override {
    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
    // Some Fetchers may call callbacks inside its ctor, in such case |fetcher_|
    // hasn't been assigned and a default value is returned.
    return fetcher_ ? fetcher_->last_url_origin() : Origin();
  }
  bool did_fail_from_transient_error() const override {
    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
    // Some Fetchers may call callbacks inside its ctor, in such case |fetcher_|
    // hasn't been assigned and a default value is returned.
    return fetcher_ ? fetcher_->did_fail_from_transient_error() : false;
  }

 private:
  THREAD_CHECKER(thread_checker_);

  std::unique_ptr<CachedFetcherHandler> handler_;
  std::unique_ptr<Fetcher> fetcher_;
};

// Fulfills the request directly using the data passed to ctor.
class CachedFetcher : public Fetcher {
 public:
  CachedFetcher(const GURL& url,
                const scoped_refptr<net::HttpResponseHeaders>& headers,
                const char* data, size_t size, const Origin& last_url_origin,
                bool did_fail_from_transient_error, Handler* handler)
      : Fetcher(handler),
        last_url_origin_(last_url_origin),
        did_fail_from_transient_error_(did_fail_from_transient_error) {
    auto response_type = handler->OnResponseStarted(this, headers);
    if (response_type == kLoadResponseAbort) {
      std::string error_msg(base::StringPrintf(
          "Handler::OnResponseStarted() aborted URL %s", url.spec().c_str()));
      handler->OnError(this, error_msg.c_str());
      return;
    }
    handler->OnReceived(this, data, size);
    handler->OnDone(this);
  }

  Origin last_url_origin() const override { return last_url_origin_; }
  bool did_fail_from_transient_error() const override {
    return did_fail_from_transient_error_;
  }

 private:
  Origin last_url_origin_;
  bool did_fail_from_transient_error_;
};

}  // namespace

class FetcherCache::CacheEntry {
 public:
  CacheEntry(const scoped_refptr<net::HttpResponseHeaders>& headers,
             const Origin& last_url_origin, bool did_fail_from_transient_error,
             std::string data)
      : headers_(headers),
        last_url_origin_(last_url_origin),
        did_fail_from_transient_error_(did_fail_from_transient_error),
        data_(std::move(data)),
        capacity_(data_.capacity()) {}

  const scoped_refptr<net::HttpResponseHeaders>& headers() const {
    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
    return headers_;
  }
  const Origin& last_url_origin() const {
    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
    return last_url_origin_;
  }
  bool did_fail_from_transient_error() const {
    return did_fail_from_transient_error_;
  }
  const char* data() const {
    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
    return data_.data();
  }
  size_t size() const {
    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
    return data_.size();
  }
  size_t capacity() const {
    DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
    CHECK_EQ(capacity_, data_.capacity());
    return capacity_;
  }

 private:
  CacheEntry(const CacheEntry&) = delete;
  CacheEntry& operator=(const CacheEntry&) = delete;

  THREAD_CHECKER(thread_checker_);

  scoped_refptr<net::HttpResponseHeaders> headers_;
  const Origin last_url_origin_;
  const bool did_fail_from_transient_error_;
  const std::string data_;

  // TODO(b/270993319): For debugging cache integrity issues in production only,
  //                    remove after identifying the root cause.
  const size_t capacity_;
};

FetcherCache::FetcherCache(const char* name, size_t capacity)
    : capacity_(capacity),
      memory_size_in_bytes_(
          base::StringPrintf("Memory.%s.FetcherCache.Size", name), 0,
          "Total number of bytes currently used by the cache."),
      count_resources_cached_(
          base::StringPrintf("Count.%s.FetcherCache.Cached", name), 0,
          "The number of resources that are currently being cached.") {}

FetcherCache::~FetcherCache() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  CHECK_EQ(thread_id_, SbThreadGetId());
  CHECK(destroy_soon_called_);

  while (!cache_entries_.empty()) {
    delete cache_entries_.begin()->second;
    cache_entries_.pop_front();
  }

  total_size_ = 0;
  memory_size_in_bytes_ = 0;
  count_resources_cached_ = 0;
}

Loader::FetcherCreator FetcherCache::GetFetcherCreator(
    const GURL& url, const Loader::FetcherCreator& real_fetcher_creator) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(!real_fetcher_creator.is_null());

  return base::Bind(&FetcherCache::CreateCachedFetcher, this, url,
                    real_fetcher_creator);
}

void FetcherCache::NotifyResourceRequested(const std::string& url) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  CHECK_EQ(thread_id_, SbThreadGetId());

  auto iter = cache_entries_.find(url);
  if (iter != cache_entries_.end()) {
    auto entry = iter->second;
    cache_entries_.erase(iter);
    cache_entries_.insert(std::make_pair(url, entry));
  }
}

void FetcherCache::DestroySoon() {
#if !defined(COBALT_BUILD_TYPE_GOLD)
  CHECK(HasOneRef());
#endif  //! defined(COBALT_BUILD_TYPE_GOLD)

  destroy_soon_called_ = true;
}

std::unique_ptr<Fetcher> FetcherCache::CreateCachedFetcher(
    const GURL& url, const Loader::FetcherCreator& real_fetcher_creator,
    Fetcher::Handler* handler) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
  DCHECK(!real_fetcher_creator.is_null());
  DCHECK(handler);

#if !defined(COBALT_BUILD_TYPE_GOLD)
  CHECK(!destroy_soon_called_);
#endif  // !defined(COBALT_BUILD_TYPE_GOLD)
  CHECK_EQ(thread_id_, SbThreadGetId());

  auto iterator = cache_entries_.find(url.spec());
  if (iterator != cache_entries_.end()) {
    auto entry = iterator->second;
    cache_entries_.erase(iterator);
    cache_entries_.insert(std::make_pair(url.spec(), entry));
    return std::unique_ptr<Fetcher>(
        new CachedFetcher(url, entry->headers(), entry->data(), entry->size(),
                          entry->last_url_origin(),
                          entry->did_fail_from_transient_error(), handler));
  }

  std::unique_ptr<CachedFetcherHandler> cached_handler(new CachedFetcherHandler(
      url.spec(), handler, base::Bind(&FetcherCache::OnFetchSuccess, this)));
  return std::unique_ptr<Fetcher>(
      new OngoingFetcher(std::move(cached_handler), real_fetcher_creator));
}

void FetcherCache::OnFetchSuccess(
    const std::string& url,
    const scoped_refptr<net::HttpResponseHeaders>& headers,
    const Origin& last_url_origin, bool did_fail_from_transient_error,
    std::string data) {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

#if !defined(COBALT_BUILD_TYPE_GOLD)
  CHECK(!destroy_soon_called_);
#endif  // !defined(COBALT_BUILD_TYPE_GOLD)
  CHECK_EQ(thread_id_, SbThreadGetId());

  if (data.capacity() > capacity_) {
    return;
  }

  auto entry = new CacheEntry(headers, last_url_origin,
                              did_fail_from_transient_error, std::move(data));

  bool inserted = cache_entries_.insert(std::make_pair(url, entry)).second;
  if (!inserted) {
    // The resource is already cached.
    delete entry;
    return;
  }

  total_size_ += entry->capacity();
  ++count_resources_cached_;
  // TODO(b/270993319): For debugging cache integrity issues in production
  //                    only, remove after identifying the root cause.
  CHECK_EQ(count_resources_cached_, static_cast<int>(cache_entries_.size()));

  while (total_size_ > capacity_) {
    // TODO(b/270993319): For debugging cache integrity issues in production
    //                    only, remove after identifying the root cause.
    CHECK(!cache_entries_.empty());
    CHECK_GE(total_size_, cache_entries_.begin()->second->capacity());

    total_size_ -= cache_entries_.begin()->second->capacity();
    delete cache_entries_.begin()->second;
    cache_entries_.pop_front();
    --count_resources_cached_;
  }

  memory_size_in_bytes_ = total_size_;
}

}  // namespace loader
}  // namespace cobalt
