// Copyright (c) 2012 The Chromium 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 "chrome/browser/history/top_sites_cache.h"

#include "base/logging.h"
#include "base/memory/ref_counted_memory.h"

namespace history {

TopSitesCache::CanonicalURLQuery::CanonicalURLQuery(const GURL& url) {
  most_visited_url_.redirects.push_back(url);
  entry_.first = &most_visited_url_;
  entry_.second = 0u;
}

TopSitesCache::CanonicalURLQuery::~CanonicalURLQuery() {
}

TopSitesCache::TopSitesCache() {
  clear_query_ref_.ClearQuery();
  clear_query_ref_.ClearRef();
  clear_path_query_ref_.ClearQuery();
  clear_path_query_ref_.ClearRef();
  clear_path_query_ref_.ClearPath();
}

TopSitesCache::~TopSitesCache() {
}

void TopSitesCache::SetTopSites(const MostVisitedURLList& top_sites) {
  top_sites_ = top_sites;
  CountForcedURLs();
  GenerateCanonicalURLs();
}

void TopSitesCache::SetThumbnails(const URLToImagesMap& images) {
  images_ = images;
}

Images* TopSitesCache::GetImage(const GURL& url) {
  return &images_[GetCanonicalURL(url)];
}

bool TopSitesCache::GetPageThumbnail(
    const GURL& url,
    scoped_refptr<base::RefCountedMemory>* bytes) const {
  std::map<GURL, Images>::const_iterator found =
      images_.find(GetCanonicalURL(url));
  if (found != images_.end()) {
    base::RefCountedMemory* data = found->second.thumbnail.get();
    if (data) {
      *bytes = data;
      return true;
    }
  }
  return false;
}

bool TopSitesCache::GetPageThumbnailScore(const GURL& url,
                                          ThumbnailScore* score) const {
  std::map<GURL, Images>::const_iterator found =
      images_.find(GetCanonicalURL(url));
  if (found != images_.end()) {
    *score = found->second.thumbnail_score;
    return true;
  }
  return false;
}

const GURL& TopSitesCache::GetCanonicalURL(const GURL& url) const {
  CanonicalURLs::const_iterator it = GetCanonicalURLsIterator(url);
  return it == canonical_urls_.end() ? url : it->first.first->url;
}

GURL TopSitesCache::GetGeneralizedCanonicalURL(const GURL& url) const {
  CanonicalURLs::const_iterator it_hi =
      canonical_urls_.lower_bound(CanonicalURLQuery(url).entry());
  if (it_hi != canonical_urls_.end()) {
    // Test match ignoring "?query#ref". This also handles exact match.
    if (url.ReplaceComponents(clear_query_ref_) ==
        GetURLFromIterator(it_hi).ReplaceComponents(clear_query_ref_)) {
      return it_hi->first.first->url;
    }
  }
  // Everything on or after |it_hi| is irrelevant.

  GURL base_url(url.ReplaceComponents(clear_path_query_ref_));
  CanonicalURLs::const_iterator it_lo =
      canonical_urls_.lower_bound(CanonicalURLQuery(base_url).entry());
  if (it_lo == canonical_urls_.end())
    return GURL::EmptyGURL();
  GURL compare_url_lo(GetURLFromIterator(it_lo));
  if (!HaveSameSchemeHostAndPort(base_url, compare_url_lo) ||
      !IsPathPrefix(base_url.path(), compare_url_lo.path())) {
    return GURL::EmptyGURL();
  }
  // Everything before |it_lo| is irrelevant.

  // Search in [|it_lo|, |it_hi|) in reversed order. The first URL found that's
  // a prefix of |url| (ignoring "?query#ref") would be returned.
  for (CanonicalURLs::const_iterator it = it_hi; it != it_lo;) {
    --it;
    GURL compare_url(GetURLFromIterator(it));
    DCHECK(HaveSameSchemeHostAndPort(compare_url, url));
    if (IsPathPrefix(compare_url.path(), url.path()))
      return it->first.first->url;
  }

  return GURL::EmptyGURL();
}

bool TopSitesCache::IsKnownURL(const GURL& url) const {
  return GetCanonicalURLsIterator(url) != canonical_urls_.end();
}

size_t TopSitesCache::GetURLIndex(const GURL& url) const {
  DCHECK(IsKnownURL(url));
  return GetCanonicalURLsIterator(url)->second;
}

size_t TopSitesCache::GetNumNonForcedURLs() const {
  return top_sites_.size() - num_forced_urls_;
}

size_t TopSitesCache::GetNumForcedURLs() const {
  return num_forced_urls_;
}

void TopSitesCache::CountForcedURLs() {
  num_forced_urls_ = 0;
  while (num_forced_urls_ < top_sites_.size()) {
    // Forced sites are all at the beginning.
    if (top_sites_[num_forced_urls_].last_forced_time.is_null())
      break;
    num_forced_urls_++;
  }
  // In debug, ensure the cache user has no forced URLs pass that point.
  if (DCHECK_IS_ON()) {
    for (size_t i = num_forced_urls_; i < top_sites_.size(); ++i) {
      DCHECK(top_sites_[i].last_forced_time.is_null())
          << "All the forced URLs must appear before non-forced URLs.";
    }
  }
}

void TopSitesCache::GenerateCanonicalURLs() {
  canonical_urls_.clear();
  for (size_t i = 0; i < top_sites_.size(); i++)
    StoreRedirectChain(top_sites_[i].redirects, i);
}

void TopSitesCache::StoreRedirectChain(const RedirectList& redirects,
                                       size_t destination) {
  // |redirects| is empty if the user pinned a site and there are not enough top
  // sites before the pinned site.

  // Map all the redirected URLs to the destination.
  for (size_t i = 0; i < redirects.size(); i++) {
    // If this redirect is already known, don't replace it with a new one.
    if (!IsKnownURL(redirects[i])) {
      CanonicalURLEntry entry;
      entry.first = &(top_sites_[destination]);
      entry.second = i;
      canonical_urls_[entry] = destination;
    }
  }
}

TopSitesCache::CanonicalURLs::const_iterator
    TopSitesCache::GetCanonicalURLsIterator(const GURL& url) const {
  return canonical_urls_.find(CanonicalURLQuery(url).entry());
}

const GURL& TopSitesCache::GetURLFromIterator(
    CanonicalURLs::const_iterator it) const {
  DCHECK(it != canonical_urls_.end());
  return it->first.first->redirects[it->first.second];
}

}  // namespace history
