// 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/in_memory_history_backend.h"

#include <set>
#include <vector>

#include "base/command_line.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/history/history_notifications.h"
#include "chrome/browser/history/in_memory_database.h"
#include "chrome/browser/history/url_database.h"
#include "chrome/browser/profiles/profile.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"

namespace history {

InMemoryHistoryBackend::InMemoryHistoryBackend()
    : profile_(NULL) {
}

InMemoryHistoryBackend::~InMemoryHistoryBackend() {}

bool InMemoryHistoryBackend::Init(const base::FilePath& history_filename,
                                  URLDatabase* db) {
  db_.reset(new InMemoryDatabase);
  return db_->InitFromDisk(history_filename);
}

void InMemoryHistoryBackend::AttachToHistoryService(Profile* profile) {
  if (!db_) {
    NOTREACHED();
    return;
  }

  profile_ = profile;

  // TODO(evanm): this is currently necessitated by generate_profile, which
  // runs without a browser process. generate_profile should really create
  // a browser process, at which point this check can then be nuked.
  if (!g_browser_process)
    return;

  // Register for the notifications we care about.
  // We only want notifications for the associated profile.
  content::Source<Profile> source(profile_);
  registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URL_VISITED, source);
  registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_MODIFIED, source);
  registrar_.Add(this, chrome::NOTIFICATION_HISTORY_URLS_DELETED, source);
  registrar_.Add(
      this, chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_UPDATED, source);
  registrar_.Add(
      this, chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_DELETED, source);
  registrar_.Add(this, chrome::NOTIFICATION_TEMPLATE_URL_REMOVED, source);
}

void InMemoryHistoryBackend::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  switch (type) {
    case chrome::NOTIFICATION_HISTORY_URL_VISITED:
      OnURLVisitedOrModified(content::Details<URLVisitedDetails>(details)->row);
      break;
    case chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_UPDATED:
      OnKeywordSearchTermUpdated(
          *content::Details<KeywordSearchUpdatedDetails>(details).ptr());
      break;
    case chrome::NOTIFICATION_HISTORY_KEYWORD_SEARCH_TERM_DELETED:
      OnKeywordSearchTermDeleted(
          *content::Details<KeywordSearchDeletedDetails>(details).ptr());
      break;
    case chrome::NOTIFICATION_HISTORY_URLS_MODIFIED: {
      const URLsModifiedDetails* modified_details =
          content::Details<URLsModifiedDetails>(details).ptr();
      URLRows::const_iterator it;
      for (it = modified_details->changed_urls.begin();
           it != modified_details->changed_urls.end(); ++it) {
        OnURLVisitedOrModified(*it);
      }
      break;
    }
    case chrome::NOTIFICATION_HISTORY_URLS_DELETED:
      OnURLsDeleted(*content::Details<URLsDeletedDetails>(details).ptr());
      break;
    case chrome::NOTIFICATION_TEMPLATE_URL_REMOVED:
      // For simplicity, this will not remove the corresponding URLRows, but
      // this is okay, as the main database does not do so either.
      db_->DeleteAllSearchTermsForKeyword(
          *(content::Details<TemplateURLID>(details).ptr()));
      break;
    default:
      // For simplicity, the unit tests send us all notifications, even when
      // we haven't registered for them, so don't assert here.
      break;
  }
}

void InMemoryHistoryBackend::OnURLVisitedOrModified(const URLRow& url_row) {
  DCHECK(db_);
  DCHECK(url_row.id());
  if (url_row.typed_count() || db_->GetKeywordSearchTermRow(url_row.id(), NULL))
    db_->InsertOrUpdateURLRowByID(url_row);
  else
    db_->DeleteURLRow(url_row.id());
}

void InMemoryHistoryBackend::OnURLsDeleted(const URLsDeletedDetails& details) {
  DCHECK(db_);

  if (details.all_history) {
    // When all history is deleted, the individual URLs won't be listed. Just
    // create a new database to quickly clear everything out.
    db_.reset(new InMemoryDatabase);
    if (!db_->InitFromScratch())
      db_.reset();
    return;
  }

  // Delete all matching URLs in our database.
  for (URLRows::const_iterator row = details.rows.begin();
       row != details.rows.end(); ++row) {
    // This will also delete the corresponding keyword search term.
    // Ignore errors, as we typically only cache a subset of URLRows.
    db_->DeleteURLRow(row->id());
  }
}

void InMemoryHistoryBackend::OnKeywordSearchTermUpdated(
    const KeywordSearchUpdatedDetails& details) {
  DCHECK(details.url_row.id());
  db_->InsertOrUpdateURLRowByID(details.url_row);
  db_->SetKeywordSearchTermsForURL(
      details.url_row.id(), details.keyword_id, details.term);
}

void InMemoryHistoryBackend::OnKeywordSearchTermDeleted(
    const KeywordSearchDeletedDetails& details) {
  // For simplicity, this will not remove the corresponding URLRow, but this is
  // okay, as the main database does not do so either.
  db_->DeleteKeywordSearchTermForURL(details.url_row_id);
}

}  // namespace history
