// Copyright 2013 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/android/most_visited_sites.h"

#include <string>
#include <vector>

#include "base/android/jni_android.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/android/scoped_java_ref.h"
#include "base/callback.h"
#include "base/metrics/histogram.h"
#include "base/metrics/sparse_histogram.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/history/top_sites.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/profiles/profile_android.h"
#include "chrome/browser/search/suggestions/suggestions_service_factory.h"
#include "chrome/browser/search/suggestions/suggestions_source.h"
#include "chrome/browser/sync/profile_sync_service.h"
#include "chrome/browser/sync/profile_sync_service_factory.h"
#include "chrome/browser/thumbnails/thumbnail_list_source.h"
#include "components/suggestions/suggestions_service.h"
#include "components/suggestions/suggestions_utils.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/url_data_source.h"
#include "jni/MostVisitedSites_jni.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/android/java_bitmap.h"
#include "ui/gfx/codec/jpeg_codec.h"

using base::android::AttachCurrentThread;
using base::android::ConvertUTF8ToJavaString;
using base::android::ConvertJavaStringToUTF8;
using base::android::ScopedJavaGlobalRef;
using base::android::ToJavaArrayOfStrings;
using base::android::CheckException;
using content::BrowserThread;
using history::TopSites;
using suggestions::ChromeSuggestion;
using suggestions::SuggestionsProfile;
using suggestions::SuggestionsService;
using suggestions::SuggestionsServiceFactory;
using suggestions::SyncState;

namespace {

// Total number of tiles displayed.
const char kNumTilesHistogramName[] = "NewTabPage.NumberOfTiles";
// Tracking thumbnails.
const char kNumLocalThumbnailTilesHistogramName[] =
    "NewTabPage.NumberOfThumbnailTiles";
const char kNumEmptyTilesHistogramName[] = "NewTabPage.NumberOfGrayTiles";
const char kNumServerTilesHistogramName[] = "NewTabPage.NumberOfExternalTiles";
// Client suggestion opened.
const char kOpenedItemClientHistogramName[] = "NewTabPage.MostVisited.client";
// Control group suggestion opened.
const char kOpenedItemControlHistogramName[] = "NewTabPage.MostVisited.client0";
// Server suggestion opened, no provider.
const char kOpenedItemServerHistogramName[] = "NewTabPage.MostVisited.server";
// Server suggestion opened with provider.
const char kOpenedItemServerProviderHistogramFormat[] =
    "NewTabPage.MostVisited.server%d";
// Client impression.
const char kImpressionClientHistogramName[] =
    "NewTabPage.SuggestionsImpression.client";
// Control group impression.
const char kImpressionControlHistogramName[] =
    "NewTabPage.SuggestionsImpression.client0";
// Server suggestion impression, no provider.
const char kImpressionServerHistogramName[] =
    "NewTabPage.SuggestionsImpression.server";
// Server suggestion impression with provider.
const char kImpressionServerHistogramFormat[] =
    "NewTabPage.SuggestionsImpression.server%d";

void ExtractMostVisitedTitlesAndURLs(
    const history::MostVisitedURLList& visited_list,
    std::vector<base::string16>* titles,
    std::vector<std::string>* urls,
    int num_sites) {
  size_t max = static_cast<size_t>(num_sites);
  for (size_t i = 0; i < visited_list.size() && i < max; ++i) {
    const history::MostVisitedURL& visited = visited_list[i];

    if (visited.url.is_empty())
      break;  // This is the signal that there are no more real visited sites.

    titles->push_back(visited.title);
    urls->push_back(visited.url.spec());
  }
}

SkBitmap ExtractThumbnail(const base::RefCountedMemory& image_data) {
  scoped_ptr<SkBitmap> image(gfx::JPEGCodec::Decode(
      image_data.front(),
      image_data.size()));
  return image.get() ? *image : SkBitmap();
}

void AddForcedURLOnUIThread(scoped_refptr<history::TopSites> top_sites,
                            const GURL& url) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  top_sites->AddForcedURL(url, base::Time::Now());
}

// Runs on the DB thread.
void GetUrlThumbnailTask(
    std::string url_string,
    scoped_refptr<TopSites> top_sites,
    ScopedJavaGlobalRef<jobject>* j_callback,
    MostVisitedSites::LookupSuccessCallback lookup_success_ui_callback,
    base::Closure lookup_failed_ui_callback) {
  JNIEnv* env = AttachCurrentThread();

  ScopedJavaGlobalRef<jobject>* j_bitmap_ref =
      new ScopedJavaGlobalRef<jobject>();

  GURL gurl(url_string);

  scoped_refptr<base::RefCountedMemory> data;
  if (top_sites->GetPageThumbnail(gurl, false, &data)) {
    SkBitmap thumbnail_bitmap = ExtractThumbnail(*data.get());
    if (!thumbnail_bitmap.empty()) {
      j_bitmap_ref->Reset(
          env,
          gfx::ConvertToJavaBitmap(&thumbnail_bitmap).obj());
    }
  } else {
    // A thumbnail is not locally available for |gurl|. Make sure it is put in
    // the list to be fetched at the next visit to this site.
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE,
        base::Bind(AddForcedURLOnUIThread, top_sites, gurl));

    // If appropriate, return on the UI thread to execute the proper callback.
    if (!lookup_failed_ui_callback.is_null()) {
      BrowserThread::PostTask(
          BrowserThread::UI, FROM_HERE, lookup_failed_ui_callback);
      delete j_bitmap_ref;
      return;
    }
  }

  // Since j_callback is owned by this callback, when the callback falls out of
  // scope it will be deleted. We need to pass ownership to the next callback.
  ScopedJavaGlobalRef<jobject>* j_callback_pass =
      new ScopedJavaGlobalRef<jobject>(*j_callback);
  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      base::Bind(lookup_success_ui_callback, base::Owned(j_bitmap_ref),
                 base::Owned(j_callback_pass)));
}

// Log an event for a given |histogram| at a given element |position|. This
// routine exists because regular histogram macros are cached thus can't be used
// if the name of the histogram will change at a given call site.
void LogHistogramEvent(const std::string& histogram, int position,
                       int num_sites) {
  base::HistogramBase* counter = base::LinearHistogram::FactoryGet(
      histogram,
      1,
      num_sites,
      num_sites + 1,
      base::Histogram::kUmaTargetedHistogramFlag);
  if (counter)
    counter->Add(position);
}

// Return the current SyncState for use with the SuggestionsService.
SyncState GetSyncState(Profile* profile) {
  ProfileSyncService* sync =
      ProfileSyncServiceFactory::GetInstance()->GetForProfile(profile);
  if (!sync)
    return SyncState::SYNC_OR_HISTORY_SYNC_DISABLED;
  return suggestions::GetSyncState(
      sync->IsSyncEnabledAndLoggedIn(),
      sync->SyncActive(),
      sync->GetActiveDataTypes().Has(syncer::HISTORY_DELETE_DIRECTIVES));
}

}  // namespace

MostVisitedSites::MostVisitedSites(Profile* profile)
    : profile_(profile), num_sites_(0), is_control_group_(false),
      initial_load_done_(false), num_local_thumbs_(0), num_server_thumbs_(0),
      num_empty_thumbs_(0), weak_ptr_factory_(this) {
  // Register the debugging page for the Suggestions Service and the thumbnails
  // debugging page.
  content::URLDataSource::Add(profile_,
                              new suggestions::SuggestionsSource(profile_));
  content::URLDataSource::Add(profile_, new ThumbnailListSource(profile_));

  // Register this class as an observer to the sync service. It is important to
  // be notified of changes in the sync state such as initialization, sync
  // being enabled or disabled, etc.
  ProfileSyncService* profile_sync_service =
      ProfileSyncServiceFactory::GetForProfile(profile_);
  if (profile_sync_service)
    profile_sync_service->AddObserver(this);
}

MostVisitedSites::~MostVisitedSites() {
  ProfileSyncService* profile_sync_service =
      ProfileSyncServiceFactory::GetForProfile(profile_);
  if (profile_sync_service && profile_sync_service->HasObserver(this))
    profile_sync_service->RemoveObserver(this);
}

void MostVisitedSites::Destroy(JNIEnv* env, jobject obj) {
  delete this;
}

void MostVisitedSites::OnLoadingComplete(JNIEnv* env, jobject obj) {
  RecordUMAMetrics();
}

void MostVisitedSites::SetMostVisitedURLsObserver(JNIEnv* env,
                                                  jobject obj,
                                                  jobject j_observer,
                                                  jint num_sites) {
  observer_.Reset(env, j_observer);
  num_sites_ = num_sites;

  QueryMostVisitedURLs();

  history::TopSites* top_sites = profile_->GetTopSites();
  if (top_sites) {
    // TopSites updates itself after a delay. To ensure up-to-date results,
    // force an update now.
    top_sites->SyncWithHistory();

    // Register for notification when TopSites changes so that we can update
    // ourself.
    registrar_.Add(this, chrome::NOTIFICATION_TOP_SITES_CHANGED,
                   content::Source<history::TopSites>(top_sites));
  }
}

// Called from the UI Thread.
void MostVisitedSites::GetURLThumbnail(JNIEnv* env,
                                       jobject obj,
                                       jstring url,
                                       jobject j_callback_obj) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  ScopedJavaGlobalRef<jobject>* j_callback =
      new ScopedJavaGlobalRef<jobject>();
  j_callback->Reset(env, j_callback_obj);

  std::string url_string = ConvertJavaStringToUTF8(env, url);
  scoped_refptr<TopSites> top_sites(profile_->GetTopSites());

  // If the Suggestions service is enabled and in use, create a callback to
  // fetch a server thumbnail from it, in case the local thumbnail is not found.
  SuggestionsService* suggestions_service =
      SuggestionsServiceFactory::GetForProfile(profile_);
  bool use_suggestions_service = suggestions_service &&
      mv_source_ == SUGGESTIONS_SERVICE;
  base::Closure lookup_failed_callback = use_suggestions_service ?
      base::Bind(&MostVisitedSites::GetSuggestionsThumbnailOnUIThread,
                 weak_ptr_factory_.GetWeakPtr(),
                 suggestions_service, url_string,
                 base::Owned(new ScopedJavaGlobalRef<jobject>(*j_callback))) :
      base::Closure();
  LookupSuccessCallback lookup_success_callback =
      base::Bind(&MostVisitedSites::OnObtainedThumbnail,
                 weak_ptr_factory_.GetWeakPtr());

  BrowserThread::PostTask(
      BrowserThread::DB, FROM_HERE,
          base::Bind(
              &GetUrlThumbnailTask, url_string, top_sites,
              base::Owned(j_callback), lookup_success_callback,
              lookup_failed_callback));
}

void MostVisitedSites::BlacklistUrl(JNIEnv* env,
                                    jobject obj,
                                    jstring j_url) {
  std::string url = ConvertJavaStringToUTF8(env, j_url);

  switch (mv_source_) {
    case TOP_SITES: {
      TopSites* top_sites = profile_->GetTopSites();
      DCHECK(top_sites);
      top_sites->AddBlacklistedURL(GURL(url));
      break;
    }

    case SUGGESTIONS_SERVICE: {
      SuggestionsService* suggestions_service =
          SuggestionsServiceFactory::GetForProfile(profile_);
      DCHECK(suggestions_service);
      suggestions_service->BlacklistURL(
          GURL(url),
          base::Bind(
              &MostVisitedSites::OnSuggestionsProfileAvailable,
              weak_ptr_factory_.GetWeakPtr(),
              base::Owned(new ScopedJavaGlobalRef<jobject>(observer_))));
      break;
    }
  }
}

void MostVisitedSites::RecordOpenedMostVisitedItem(JNIEnv* env,
                                                   jobject obj,
                                                   jint index) {
  switch (mv_source_) {
    case TOP_SITES: {
      const std::string histogram = is_control_group_ ?
          kOpenedItemControlHistogramName : kOpenedItemClientHistogramName;
      LogHistogramEvent(histogram, index, num_sites_);
      break;
    }
    case SUGGESTIONS_SERVICE: {
      if (server_suggestions_.suggestions_size() > index) {
        if (server_suggestions_.suggestions(index).providers_size()) {
          std::string histogram = base::StringPrintf(
              kOpenedItemServerProviderHistogramFormat,
              server_suggestions_.suggestions(index).providers(0));
          LogHistogramEvent(histogram, index, num_sites_);
        } else {
          UMA_HISTOGRAM_SPARSE_SLOWLY(kOpenedItemServerHistogramName, index);
        }
      }
      break;
    }
  }
}

void MostVisitedSites::Observe(int type,
                               const content::NotificationSource& source,
                               const content::NotificationDetails& details) {
  DCHECK_EQ(type, chrome::NOTIFICATION_TOP_SITES_CHANGED);

  if (mv_source_ == TOP_SITES) {
    // The displayed suggestions are invalidated.
    QueryMostVisitedURLs();
  }
}

void MostVisitedSites::OnStateChanged() {
  // There have been changes to the sync state. This class cares about a few
  // (just initialized, enabled/disabled or history sync state changed). Re-run
  // the query code which will use the proper state.
  QueryMostVisitedURLs();
}

// static
bool MostVisitedSites::Register(JNIEnv* env) {
  return RegisterNativesImpl(env);
}

void MostVisitedSites::QueryMostVisitedURLs() {
  SuggestionsService* suggestions_service =
      SuggestionsServiceFactory::GetForProfile(profile_);
  if (suggestions_service) {
    // Suggestions service is enabled, initiate a query.
    suggestions_service->FetchSuggestionsData(
        GetSyncState(profile_),
        base::Bind(
          &MostVisitedSites::OnSuggestionsProfileAvailable,
          weak_ptr_factory_.GetWeakPtr(),
          base::Owned(new ScopedJavaGlobalRef<jobject>(observer_))));
  } else {
    InitiateTopSitesQuery();
  }
}

void MostVisitedSites::InitiateTopSitesQuery() {
  TopSites* top_sites = profile_->GetTopSites();
  if (!top_sites)
    return;

  top_sites->GetMostVisitedURLs(
      base::Bind(
          &MostVisitedSites::OnMostVisitedURLsAvailable,
          weak_ptr_factory_.GetWeakPtr(),
          base::Owned(new ScopedJavaGlobalRef<jobject>(observer_)),
          num_sites_),
      false);
}

void MostVisitedSites::OnMostVisitedURLsAvailable(
    ScopedJavaGlobalRef<jobject>* j_observer,
    int num_sites,
    const history::MostVisitedURLList& visited_list) {
  std::vector<base::string16> titles;
  std::vector<std::string> urls;
  ExtractMostVisitedTitlesAndURLs(visited_list, &titles, &urls, num_sites);

  mv_source_ = TOP_SITES;

  // Only log impression metrics on the initial load of the NTP.
  if (!initial_load_done_) {
    int num_tiles = urls.size();
    UMA_HISTOGRAM_SPARSE_SLOWLY(kNumTilesHistogramName, num_tiles);
    const std::string histogram = is_control_group_ ?
        kImpressionControlHistogramName : kImpressionClientHistogramName;
    for (int i = 0; i < num_tiles; ++i) {
      LogHistogramEvent(histogram, i, num_sites_);
    }
  }
  initial_load_done_ = true;

  JNIEnv* env = AttachCurrentThread();
  Java_MostVisitedURLsObserver_onMostVisitedURLsAvailable(
      env,
      j_observer->obj(),
      ToJavaArrayOfStrings(env, titles).obj(),
      ToJavaArrayOfStrings(env, urls).obj());
}

void MostVisitedSites::OnSuggestionsProfileAvailable(
    ScopedJavaGlobalRef<jobject>* j_observer,
    const SuggestionsProfile& suggestions_profile) {
  int size = suggestions_profile.suggestions_size();

  // Determine if the user is in a control group (they would have received
  // suggestions, but are in a group where they shouldn't).
  is_control_group_ = size && SuggestionsService::IsControlGroup();

  // If no suggestions data is available or the user is in a control group,
  // initiate Top Sites query.
  if (is_control_group_ || !size) {
    InitiateTopSitesQuery();
    return;
  }

  std::vector<base::string16> titles;
  std::vector<std::string> urls;

  int i = 0;
  for (; i < size && i < num_sites_; ++i) {
    const ChromeSuggestion& suggestion = suggestions_profile.suggestions(i);
    titles.push_back(base::UTF8ToUTF16(suggestion.title()));
    urls.push_back(suggestion.url());
    // Only log impression metrics on the initial NTP load.
    if (!initial_load_done_) {
      if (suggestion.providers_size()) {
        std::string histogram = base::StringPrintf(
            kImpressionServerHistogramFormat, suggestion.providers(0));
        LogHistogramEvent(histogram, i, num_sites_);
      } else {
        UMA_HISTOGRAM_SPARSE_SLOWLY(kImpressionServerHistogramName, i);
      }
    }
  }
  if (!initial_load_done_) {
    UMA_HISTOGRAM_SPARSE_SLOWLY(kNumTilesHistogramName, i);
  }
  initial_load_done_ = true;

  mv_source_ = SUGGESTIONS_SERVICE;
  // Keep a copy of the suggestions for eventual logging.
  server_suggestions_ = suggestions_profile;

  JNIEnv* env = AttachCurrentThread();
  Java_MostVisitedURLsObserver_onMostVisitedURLsAvailable(
      env,
      j_observer->obj(),
      ToJavaArrayOfStrings(env, titles).obj(),
      ToJavaArrayOfStrings(env, urls).obj());
}

void MostVisitedSites::OnObtainedThumbnail(
    ScopedJavaGlobalRef<jobject>* bitmap,
    ScopedJavaGlobalRef<jobject>* j_callback) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  JNIEnv* env = AttachCurrentThread();
  if (bitmap->obj()) {
    num_local_thumbs_++;
  } else {
    num_empty_thumbs_++;
  }
  Java_ThumbnailCallback_onMostVisitedURLsThumbnailAvailable(
      env, j_callback->obj(), bitmap->obj());
}

void MostVisitedSites::GetSuggestionsThumbnailOnUIThread(
    SuggestionsService* suggestions_service,
    const std::string& url_string,
    ScopedJavaGlobalRef<jobject>* j_callback) {
  suggestions_service->GetPageThumbnail(
      GURL(url_string),
      base::Bind(&MostVisitedSites::OnSuggestionsThumbnailAvailable,
                 weak_ptr_factory_.GetWeakPtr(),
                 base::Owned(new ScopedJavaGlobalRef<jobject>(*j_callback))));
}

void MostVisitedSites::OnSuggestionsThumbnailAvailable(
    ScopedJavaGlobalRef<jobject>* j_callback,
    const GURL& url,
    const SkBitmap* bitmap) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  JNIEnv* env = AttachCurrentThread();

  ScopedJavaGlobalRef<jobject>* j_bitmap_ref =
      new ScopedJavaGlobalRef<jobject>();
  if (bitmap) {
    num_server_thumbs_++;
    j_bitmap_ref->Reset(
        env,
        gfx::ConvertToJavaBitmap(bitmap).obj());
  } else {
    num_empty_thumbs_++;
  }

  Java_ThumbnailCallback_onMostVisitedURLsThumbnailAvailable(
      env, j_callback->obj(), j_bitmap_ref->obj());
}

void MostVisitedSites::RecordUMAMetrics() {
  UMA_HISTOGRAM_SPARSE_SLOWLY(kNumLocalThumbnailTilesHistogramName,
                              num_local_thumbs_);
  num_local_thumbs_ = 0;
  UMA_HISTOGRAM_SPARSE_SLOWLY(kNumEmptyTilesHistogramName, num_empty_thumbs_);
  num_empty_thumbs_ = 0;
  UMA_HISTOGRAM_SPARSE_SLOWLY(kNumServerTilesHistogramName, num_server_thumbs_);
  num_server_thumbs_ = 0;
}

static jlong Init(JNIEnv* env, jobject obj, jobject jprofile) {
  MostVisitedSites* most_visited_sites =
      new MostVisitedSites(ProfileAndroid::FromProfileAndroid(jprofile));
  return reinterpret_cast<intptr_t>(most_visited_sites);
}
