// Copyright (c) 2011 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/instant/instant_controller.h"

#include "base/command_line.h"
#include "base/message_loop.h"
#include "base/metrics/histogram.h"
#include "build/build_config.h"
#include "chrome/browser/autocomplete/autocomplete_match.h"
#include "chrome/browser/instant/instant_delegate.h"
#include "chrome/browser/instant/instant_loader.h"
#include "chrome/browser/instant/instant_loader_manager.h"
#include "chrome/browser/instant/promo_counter.h"
#include "chrome/browser/platform_util.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_model.h"
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "content/browser/renderer_host/render_widget_host_view.h"
#include "content/browser/tab_contents/tab_contents.h"
#include "content/common/notification_service.h"

// Number of ms to delay between loading urls.
static const int kUpdateDelayMS = 200;

// Amount of time we delay before showing pages that have a non-200 status.
static const int kShowDelayMS = 800;

// static
InstantController::HostBlacklist* InstantController::host_blacklist_ = NULL;

InstantController::InstantController(Profile* profile,
                                     InstantDelegate* delegate)
    : delegate_(delegate),
      tab_contents_(NULL),
      is_active_(false),
      displayable_loader_(NULL),
      commit_on_mouse_up_(false),
      last_transition_type_(PageTransition::LINK),
      ALLOW_THIS_IN_INITIALIZER_LIST(destroy_factory_(this)) {
  PrefService* service = profile->GetPrefs();
  if (service) {
    // kInstantWasEnabledOnce was added after instant, set it now to make sure
    // it is correctly set.
    service->SetBoolean(prefs::kInstantEnabledOnce, true);
  }
}

InstantController::~InstantController() {
}

// static
void InstantController::RegisterUserPrefs(PrefService* prefs) {
  prefs->RegisterBooleanPref(prefs::kInstantConfirmDialogShown, false);
  prefs->RegisterBooleanPref(prefs::kInstantEnabled, false);
  prefs->RegisterBooleanPref(prefs::kInstantEnabledOnce, false);
  prefs->RegisterInt64Pref(prefs::kInstantEnabledTime, false);
  PromoCounter::RegisterUserPrefs(prefs, prefs::kInstantPromo);
}

// static
void InstantController::RecordMetrics(Profile* profile) {
  if (!IsEnabled(profile))
    return;

  PrefService* service = profile->GetPrefs();
  if (service) {
    int64 enable_time = service->GetInt64(prefs::kInstantEnabledTime);
    if (!enable_time) {
      service->SetInt64(prefs::kInstantEnabledTime,
                        base::Time::Now().ToInternalValue());
    } else {
      base::TimeDelta delta =
          base::Time::Now() - base::Time::FromInternalValue(enable_time);
      // Histogram from 1 hour to 30 days.
      UMA_HISTOGRAM_CUSTOM_COUNTS("Instant.EnabledTime.Predictive",
                                  delta.InHours(), 1, 30 * 24, 50);
    }
  }
}

// static
bool InstantController::IsEnabled(Profile* profile) {
  PrefService* prefs = profile->GetPrefs();
  return prefs->GetBoolean(prefs::kInstantEnabled);
}

// static
void InstantController::Enable(Profile* profile) {
  PromoCounter* promo_counter = profile->GetInstantPromoCounter();
  if (promo_counter)
    promo_counter->Hide();

  PrefService* service = profile->GetPrefs();
  if (!service)
    return;

  service->SetBoolean(prefs::kInstantEnabled, true);
  service->SetBoolean(prefs::kInstantConfirmDialogShown, true);
  service->SetInt64(prefs::kInstantEnabledTime,
                    base::Time::Now().ToInternalValue());
  service->SetBoolean(prefs::kInstantEnabledOnce, true);
}

// static
void InstantController::Disable(Profile* profile) {
  PrefService* service = profile->GetPrefs();
  if (!service || !IsEnabled(profile))
    return;

  int64 enable_time = service->GetInt64(prefs::kInstantEnabledTime);
  if (enable_time) {
    base::TimeDelta delta =
        base::Time::Now() - base::Time::FromInternalValue(enable_time);
    // Histogram from 1 minute to 10 days.
    UMA_HISTOGRAM_CUSTOM_COUNTS("Instant.TimeToDisable.Predictive",
                                delta.InMinutes(), 1, 60 * 24 * 10, 50);
  }

  service->SetBoolean(prefs::kInstantEnabled, false);
}

// static
bool InstantController::CommitIfCurrent(InstantController* controller) {
  if (controller && controller->IsCurrent()) {
    controller->CommitCurrentPreview(INSTANT_COMMIT_PRESSED_ENTER);
    return true;
  }
  return false;
}

void InstantController::Update(TabContentsWrapper* tab_contents,
                               const AutocompleteMatch& match,
                               const string16& user_text,
                               bool verbatim,
                               string16* suggested_text) {
  suggested_text->clear();

  if (tab_contents != tab_contents_)
    DestroyPreviewContents();

  const GURL& url = match.destination_url;
  tab_contents_ = tab_contents;
  commit_on_mouse_up_ = false;
  last_transition_type_ = match.transition;
  const TemplateURL* template_url = NULL;

  if (url.is_empty() || !url.is_valid()) {
    // Assume we were invoked with GURL() and should destroy all.
    DestroyPreviewContents();
    return;
  }

  if (!ShouldShowPreviewFor(match, &template_url)) {
    DestroyPreviewContentsAndLeaveActive();
    return;
  }

  if (!loader_manager_.get())
    loader_manager_.reset(new InstantLoaderManager(this));

  if (!is_active_) {
    is_active_ = true;
    delegate_->PrepareForInstant();
  }

  TemplateURLID template_url_id = template_url ? template_url->id() : 0;
  // Verbatim only makes sense if the search engines supports instant.
  bool real_verbatim = template_url_id ? verbatim : false;

  if (ShouldUpdateNow(template_url_id, match.destination_url)) {
    UpdateLoader(template_url, match.destination_url, match.transition,
                 user_text, real_verbatim, suggested_text);
  } else {
    ScheduleUpdate(match.destination_url);
  }

  NotificationService::current()->Notify(
      NotificationType::INSTANT_CONTROLLER_UPDATED,
      Source<InstantController>(this),
      NotificationService::NoDetails());
}

void InstantController::SetOmniboxBounds(const gfx::Rect& bounds) {
  if (omnibox_bounds_ == bounds)
    return;

  // Always track the omnibox bounds. That way if Update is later invoked the
  // bounds are in sync.
  omnibox_bounds_ = bounds;
  if (loader_manager_.get()) {
    if (loader_manager_->current_loader())
      loader_manager_->current_loader()->SetOmniboxBounds(bounds);
    if (loader_manager_->pending_loader())
      loader_manager_->pending_loader()->SetOmniboxBounds(bounds);
  }
}

void InstantController::DestroyPreviewContents() {
  if (!loader_manager_.get()) {
    // We're not showing anything, nothing to do.
    return;
  }

  // ReleasePreviewContents sets is_active_ to false, but we need to set it
  // before notifying the delegate, otherwise if the delegate asks for the state
  // we'll still be active.
  is_active_ = false;
  delegate_->HideInstant();
  delete ReleasePreviewContents(INSTANT_COMMIT_DESTROY);
}

void InstantController::DestroyPreviewContentsAndLeaveActive() {
  commit_on_mouse_up_ = false;
  if (displayable_loader_) {
    displayable_loader_ = NULL;
    delegate_->HideInstant();
  }

  // TODO(sky): this shouldn't nuke the loader. It should just nuke non-instant
  // loaders and hide instant loaders.
  loader_manager_.reset(new InstantLoaderManager(this));
  show_timer_.Stop();
  update_timer_.Stop();
}

bool InstantController::IsCurrent() {
  return loader_manager_.get() && loader_manager_->active_loader() &&
      loader_manager_->active_loader()->ready() &&
      !loader_manager_->active_loader()->needs_reload() &&
      !update_timer_.IsRunning();
}

void InstantController::CommitCurrentPreview(InstantCommitType type) {
  if (type == INSTANT_COMMIT_PRESSED_ENTER && show_timer_.IsRunning()) {
    // The user pressed enter and the show timer is running. This means the
    // pending_loader returned an error code and we're not showing it. Force it
    // to be shown.
    show_timer_.Stop();
    ShowTimerFired();
  }
  DCHECK(loader_manager_.get());
  DCHECK(loader_manager_->current_loader());
  bool showing_instant =
      loader_manager_->current_loader()->is_showing_instant();
  TabContentsWrapper* tab = ReleasePreviewContents(type);
  // If the loader was showing an instant page then it's navigation stack is
  // something like: search-engine-home-page (eg google.com) search-term1
  // search-term2 .... Each search-term navigation corresponds to the page
  // deciding enough time has passed to commit a navigation. We don't want the
  // searche-engine-home-page navigation in this case so we pass true to
  // CopyStateFromAndPrune to have the search-engine-home-page navigation
  // removed.
  tab->controller().CopyStateFromAndPrune(
      &tab_contents_->controller(), showing_instant);
  delegate_->CommitInstant(tab);
  CompleteRelease(tab->tab_contents());
}

void InstantController::SetCommitOnMouseUp() {
  commit_on_mouse_up_ = true;
}

bool InstantController::IsMouseDownFromActivate() {
  DCHECK(loader_manager_.get());
  DCHECK(loader_manager_->current_loader());
  return loader_manager_->current_loader()->IsMouseDownFromActivate();
}

#if defined(OS_MACOSX)
void InstantController::OnAutocompleteLostFocus(
    gfx::NativeView view_gaining_focus) {
  // If |IsMouseDownFromActivate()| returns false, the RenderWidgetHostView did
  // not receive a mouseDown event.  Therefore, we should destroy the preview.
  // Otherwise, the RWHV was clicked, so we commit the preview.
  if (!is_displayable() || !GetPreviewContents() ||
      !IsMouseDownFromActivate()) {
    DestroyPreviewContents();
  } else if (IsShowingInstant()) {
    SetCommitOnMouseUp();
  } else {
    CommitCurrentPreview(INSTANT_COMMIT_FOCUS_LOST);
  }
}
#else
void InstantController::OnAutocompleteLostFocus(
    gfx::NativeView view_gaining_focus) {
  if (!is_active() || !GetPreviewContents()) {
    DestroyPreviewContents();
    return;
  }

  RenderWidgetHostView* rwhv =
      GetPreviewContents()->tab_contents()->GetRenderWidgetHostView();
  if (!view_gaining_focus || !rwhv) {
    DestroyPreviewContents();
    return;
  }

  gfx::NativeView tab_view =
      GetPreviewContents()->tab_contents()->GetNativeView();
  // Focus is going to the renderer.
  if (rwhv->GetNativeView() == view_gaining_focus ||
      tab_view == view_gaining_focus) {
    if (!IsMouseDownFromActivate()) {
      // If the mouse is not down, focus is not going to the renderer. Someone
      // else moved focus and we shouldn't commit.
      DestroyPreviewContents();
      return;
    }

    if (IsShowingInstant()) {
      // We're showing instant results. As instant results may shift when
      // committing we commit on the mouse up. This way a slow click still
      // works fine.
      SetCommitOnMouseUp();
      return;
    }

    CommitCurrentPreview(INSTANT_COMMIT_FOCUS_LOST);
    return;
  }

  // Walk up the view hierarchy. If the view gaining focus is a subview of the
  // TabContents view (such as a windowed plugin or http auth dialog), we want
  // to keep the preview contents. Otherwise, focus has gone somewhere else,
  // such as the JS inspector, and we want to cancel the preview.
  gfx::NativeView view_gaining_focus_ancestor = view_gaining_focus;
  while (view_gaining_focus_ancestor &&
         view_gaining_focus_ancestor != tab_view) {
    view_gaining_focus_ancestor =
        platform_util::GetParent(view_gaining_focus_ancestor);
  }

  if (view_gaining_focus_ancestor) {
    CommitCurrentPreview(INSTANT_COMMIT_FOCUS_LOST);
    return;
  }

  DestroyPreviewContents();
}
#endif

TabContentsWrapper* InstantController::ReleasePreviewContents(
    InstantCommitType type) {
  if (!loader_manager_.get())
    return NULL;

  // Make sure the pending loader is active. Ideally we would call
  // ShowTimerFired, but if Release is invoked from the browser we don't want to
  // attempt to show the tab contents (since its being added to a new tab).
  if (type == INSTANT_COMMIT_PRESSED_ENTER && show_timer_.IsRunning()) {
    InstantLoader* loader = loader_manager_->active_loader();
    if (loader && loader->ready() &&
        loader == loader_manager_->pending_loader()) {
      scoped_ptr<InstantLoader> old_loader;
      loader_manager_->MakePendingCurrent(&old_loader);
    }
  }

  // Loader may be null if the url blacklisted instant.
  scoped_ptr<InstantLoader> loader;
  if (loader_manager_->current_loader())
    loader.reset(loader_manager_->ReleaseCurrentLoader());
  TabContentsWrapper* tab = loader.get() ?
      loader->ReleasePreviewContents(type) : NULL;

  ClearBlacklist();
  is_active_ = false;
  displayable_loader_ = NULL;
  commit_on_mouse_up_ = false;
  omnibox_bounds_ = gfx::Rect();
  loader_manager_.reset();
  update_timer_.Stop();
  show_timer_.Stop();
  return tab;
}

void InstantController::CompleteRelease(TabContents* tab) {
  tab->SetAllContentsBlocked(false);
}

TabContentsWrapper* InstantController::GetPreviewContents() {
  return loader_manager_.get() && loader_manager_->current_loader() ?
      loader_manager_->current_loader()->preview_contents() : NULL;
}

bool InstantController::IsShowingInstant() {
  return loader_manager_.get() && loader_manager_->current_loader() &&
      loader_manager_->current_loader()->is_showing_instant();
}

bool InstantController::MightSupportInstant() {
  return loader_manager_.get() && loader_manager_->active_loader() &&
      loader_manager_->active_loader()->is_showing_instant();
}

GURL InstantController::GetCurrentURL() {
  return loader_manager_.get() && loader_manager_->active_loader() ?
      loader_manager_->active_loader()->url() : GURL();
}

void InstantController::InstantStatusChanged(InstantLoader* loader) {
  if (!loader->http_status_ok()) {
    // Status isn't ok, start a timer that when fires shows the result. This
    // delays showing 403 pages and the like.
    show_timer_.Stop();
    show_timer_.Start(
        base::TimeDelta::FromMilliseconds(kShowDelayMS),
        this, &InstantController::ShowTimerFired);
    UpdateDisplayableLoader();
    return;
  }

  ProcessInstantStatusChanged(loader);
}

void InstantController::SetSuggestedTextFor(
    InstantLoader* loader,
    const string16& text,
    InstantCompleteBehavior behavior) {
  if (loader_manager_->current_loader() == loader)
    delegate_->SetSuggestedText(text, behavior);
}

gfx::Rect InstantController::GetInstantBounds() {
  return delegate_->GetInstantBounds();
}

bool InstantController::ShouldCommitInstantOnMouseUp() {
  return commit_on_mouse_up_;
}

void InstantController::CommitInstantLoader(InstantLoader* loader) {
  if (loader_manager_.get() && loader_manager_->current_loader() == loader) {
    CommitCurrentPreview(INSTANT_COMMIT_FOCUS_LOST);
  } else {
    // This can happen if the mouse was down, we swapped out the preview and
    // the mouse was released. Generally this shouldn't happen, but if it does
    // revert.
    DestroyPreviewContents();
  }
}

void InstantController::InstantLoaderDoesntSupportInstant(
    InstantLoader* loader) {
  DCHECK(!loader->ready());  // We better not be showing this loader.
  DCHECK(loader->template_url_id());

  VLOG(1) << "provider does not support instant";

  // Don't attempt to use instant for this search engine again.
  BlacklistFromInstant(loader->template_url_id());

  // Because of the state of the stack we can't destroy the loader now.
  bool was_pending = loader_manager_->pending_loader() == loader;
  ScheduleDestroy(loader_manager_->ReleaseLoader(loader));
  if (was_pending) {
    // |loader| was the pending loader. We may be showing another TabContents to
    // the user (what was current). Destroy it.
    DestroyPreviewContentsAndLeaveActive();
  } else {
    // |loader| wasn't pending, yet it may still be the displayed loader.
    UpdateDisplayableLoader();
  }
}

void InstantController::AddToBlacklist(InstantLoader* loader, const GURL& url) {
  std::string host = url.host();
  if (host.empty())
    return;

  if (!host_blacklist_)
    host_blacklist_ = new HostBlacklist;
  host_blacklist_->insert(host);

  if (!loader_manager_.get())
    return;

  // Because of the state of the stack we can't destroy the loader now.
  ScheduleDestroy(loader);

  loader_manager_->ReleaseLoader(loader);

  UpdateDisplayableLoader();
}

void InstantController::UpdateDisplayableLoader() {
  InstantLoader* loader = NULL;
  // As soon as the pending loader is displayable it becomes the current loader,
  // so we need only concern ourselves with the current loader here.
  if (loader_manager_.get() && loader_manager_->current_loader() &&
      loader_manager_->current_loader()->ready() &&
      (!show_timer_.IsRunning() ||
       loader_manager_->current_loader()->http_status_ok())) {
    loader = loader_manager_->current_loader();
  }
  if (loader == displayable_loader_)
    return;

  displayable_loader_ = loader;

  if (!displayable_loader_) {
    delegate_->HideInstant();
  } else {
    delegate_->ShowInstant(displayable_loader_->preview_contents());
    NotificationService::current()->Notify(
        NotificationType::INSTANT_CONTROLLER_SHOWN,
        Source<InstantController>(this),
        NotificationService::NoDetails());
  }
}

TabContentsWrapper* InstantController::GetPendingPreviewContents() {
  return loader_manager_.get() && loader_manager_->pending_loader() ?
      loader_manager_->pending_loader()->preview_contents() : NULL;
}

bool InstantController::ShouldUpdateNow(TemplateURLID instant_id,
                                        const GURL& url) {
  DCHECK(loader_manager_.get());

  if (instant_id) {
    // Update sites that support instant immediately, they can do their own
    // throttling.
    return true;
  }

  if (url.SchemeIsFile())
    return true;  // File urls should load quickly, so don't delay loading them.

  if (loader_manager_->WillUpateChangeActiveLoader(instant_id)) {
    // If Update would change loaders, update now. This indicates transitioning
    // from an instant to non-instant loader.
    return true;
  }

  InstantLoader* active_loader = loader_manager_->active_loader();
  // WillUpateChangeActiveLoader should return true if no active loader, so
  // we know there will be an active loader if we get here.
  DCHECK(active_loader);
  // Immediately update if the url is the same (which should result in nothing
  // happening) or the hosts differ, otherwise we'll delay the update.
  return (active_loader->url() == url) ||
      (active_loader->url().host() != url.host());
}

void InstantController::ScheduleUpdate(const GURL& url) {
  scheduled_url_ = url;

  update_timer_.Stop();
  update_timer_.Start(base::TimeDelta::FromMilliseconds(kUpdateDelayMS),
                      this, &InstantController::ProcessScheduledUpdate);
}

void InstantController::ProcessScheduledUpdate() {
  DCHECK(loader_manager_.get());

  // We only delay loading of sites that don't support instant, so we can ignore
  // suggested_text here.
  string16 suggested_text;
  UpdateLoader(NULL, scheduled_url_, last_transition_type_, string16(), false,
               &suggested_text);
}

void InstantController::ProcessInstantStatusChanged(InstantLoader* loader) {
  DCHECK(loader_manager_.get());
  scoped_ptr<InstantLoader> old_loader;
  if (loader == loader_manager_->pending_loader()) {
    loader_manager_->MakePendingCurrent(&old_loader);
  } else if (loader != loader_manager_->current_loader()) {
    // Notification from a loader that is no longer the current (either we have
    // a pending, or its an instant loader). Ignore it.
    return;
  }

  UpdateDisplayableLoader();
}

void InstantController::ShowTimerFired() {
  if (!loader_manager_.get())
    return;

  InstantLoader* loader = loader_manager_->active_loader();
  if (loader && loader->ready())
    ProcessInstantStatusChanged(loader);
}

void InstantController::UpdateLoader(const TemplateURL* template_url,
                                     const GURL& url,
                                     PageTransition::Type transition_type,
                                     const string16& user_text,
                                     bool verbatim,
                                     string16* suggested_text) {
  update_timer_.Stop();

  scoped_ptr<InstantLoader> owned_loader;
  TemplateURLID template_url_id = template_url ? template_url->id() : 0;
  InstantLoader* new_loader =
      loader_manager_->UpdateLoader(template_url_id, &owned_loader);

  new_loader->SetOmniboxBounds(omnibox_bounds_);
  if (new_loader->Update(tab_contents_, template_url, url, transition_type,
                         user_text, verbatim, suggested_text)) {
    show_timer_.Stop();
    if (!new_loader->http_status_ok()) {
      show_timer_.Start(
          base::TimeDelta::FromMilliseconds(kShowDelayMS),
          this, &InstantController::ShowTimerFired);
    }
  }
  UpdateDisplayableLoader();
}

bool InstantController::ShouldShowPreviewFor(const AutocompleteMatch& match,
                                             const TemplateURL** template_url) {
  const TemplateURL* t_url = GetTemplateURL(match);
  if (t_url) {
    if (!t_url->id() ||
        !t_url->instant_url() ||
        IsBlacklistedFromInstant(t_url->id()) ||
        !t_url->instant_url()->SupportsReplacement()) {
      // To avoid extra load on other search engines we only enable previews if
      // they support the instant API.
      return false;
    }
  }
  *template_url = t_url;

  if (match.destination_url.SchemeIs(chrome::kJavaScriptScheme))
    return false;

  // Extension keywords don't have a real destionation URL.
  if (match.template_url && match.template_url->IsExtensionKeyword())
    return false;

  // Was the host blacklisted?
  if (host_blacklist_ && host_blacklist_->count(match.destination_url.host()))
    return false;

  return true;
}

void InstantController::BlacklistFromInstant(TemplateURLID id) {
  blacklisted_ids_.insert(id);
}

bool InstantController::IsBlacklistedFromInstant(TemplateURLID id) {
  return blacklisted_ids_.count(id) > 0;
}

void InstantController::ClearBlacklist() {
  blacklisted_ids_.clear();
}

void InstantController::ScheduleDestroy(InstantLoader* loader) {
  loaders_to_destroy_.push_back(loader);
  if (destroy_factory_.empty()) {
    MessageLoop::current()->PostTask(
        FROM_HERE, destroy_factory_.NewRunnableMethod(
            &InstantController::DestroyLoaders));
  }
}

void InstantController::DestroyLoaders() {
  loaders_to_destroy_.reset();
}

const TemplateURL* InstantController::GetTemplateURL(
    const AutocompleteMatch& match) {
  const TemplateURL* template_url = match.template_url;
  if (match.type == AutocompleteMatch::SEARCH_WHAT_YOU_TYPED ||
      match.type == AutocompleteMatch::SEARCH_HISTORY ||
      match.type == AutocompleteMatch::SEARCH_SUGGEST) {
    TemplateURLModel* model = tab_contents_->profile()->GetTemplateURLModel();
    template_url = model ? model->GetDefaultSearchProvider() : NULL;
  }
  return template_url;
}
