/*
 * Copyright 2017 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.
 */

#ifndef COBALT_LOADER_CORS_PREFLIGHT_CACHE_H_
#define COBALT_LOADER_CORS_PREFLIGHT_CACHE_H_

#include <memory>
#include <queue>
#include <set>
#include <string>
#include <unordered_map>
#include <vector>

#include "base/containers/hash_tables.h"
#include "base/time/time.h"
#include "net/http/http_request_headers.h"
#include "net/url_request/url_fetcher.h"
#include "starboard/common/string.h"
#include "url/gurl.h"

namespace cobalt {
namespace loader {

// https://fetch.spec.whatwg.org/#concept-cache
class CORSPreflightCache : public base::RefCounted<CORSPreflightCache> {
 public:
  // An entry is appended at the end of every preflight to avoid same
  // preflight request in the near future.
  void AppendEntry(const std::string& url_str, const std::string& origin,
                   int max_age, bool has_credentials,
                   const std::vector<std::string>& methods_vec,
                   const std::vector<std::string>& headernames_vec);
  // Check if there is a preflight cache match. This method does not include
  // checking for CORS-safelisted method and request-header.
  bool HaveEntry(const std::string& url_str, const std::string& origin,
                 bool credentials_mode_is_include,
                 const net::URLFetcher::RequestType& new_request_method,
                 const std::vector<std::string>& unsafe_headernames);

 private:
  // Case-insensitive comparator.
  struct CaseInsensitiveCompare {
    bool operator()(const std::string& lhs, const std::string& rhs) const {
      return SbStringCompareNoCase(lhs.c_str(), rhs.c_str()) < 0;
    }
  };

  // The spec wants a cache entry for every method and for every header which is
  // a little unnesessarily expensive. We create an entry for each request and
  // If there is an old entry in the new entry's pleace we simply push the old
  // one out which potentially increases cache misses slightly but reduces
  // memory cost. Chromium also takes this approach.
  // The map's first key is entry's request url and second is entry's origin.
  struct CORSPreflightCacheEntry
      : public base::RefCounted<CORSPreflightCacheEntry> {
    bool credentials;
    // True if response has "Access-Control-Allow-Methods: *".
    bool allow_all_methods;
    // True if response has "Access-Control-Allow-Headers: *".
    // Non-wildcard request-header name is "Authentication".
    bool allow_all_headers_except_non_wildcard;
    base::Time expiration_time;
    std::set<net::URLFetcher::RequestType> methods;
    std::set<std::string, CaseInsensitiveCompare> headernames;

    CORSPreflightCacheEntry()
        : credentials(false),
          allow_all_methods(false),
          allow_all_headers_except_non_wildcard(false) {}
  };

  struct ExpirationHeapEntry {
    base::Time expiration_time;
    std::string url_str;
    std::string origin;
    bool operator>(const ExpirationHeapEntry& rhs) const {
      return expiration_time > rhs.expiration_time;
    }
    bool operator<(const ExpirationHeapEntry& rhs) const {
      return expiration_time < rhs.expiration_time;
    }
  };

  // This operator constructs a min-heap.
  class ExpirationMinHeapComparator {
   public:
    bool operator()(const ExpirationHeapEntry& lhs,
                    const ExpirationHeapEntry& rhs) {
      return lhs > rhs;
    }
  };

  void ClearObsoleteEntries();

  // TODO: Replace scoped_refptr with std::unique_ptr when possible or replace
  // the map as a 'scoped_map'.
  base::hash_map<
      std::string,
      base::hash_map<std::string, scoped_refptr<CORSPreflightCacheEntry> > >
      content_;

  std::priority_queue<ExpirationHeapEntry, std::vector<ExpirationHeapEntry>,
                      ExpirationMinHeapComparator>
      expiration_time_heap_;
  THREAD_CHECKER(thread_checker_);
};

}  // namespace loader
}  // namespace cobalt
#endif  // COBALT_LOADER_CORS_PREFLIGHT_CACHE_H_
