// Copyright (c) 2010 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/possible_url_model.h"

#include "base/callback.h"
#include "base/i18n/rtl.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/favicon_service.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/pref_names.h"
#include "content/browser/cancelable_request.h"
#include "grit/app_resources.h"
#include "grit/generated_resources.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/models/table_model_observer.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/text/text_elider.h"
#include "ui/gfx/codec/png_codec.h"

using base::Time;
using base::TimeDelta;

namespace {

// The default favicon.
SkBitmap* default_favicon = NULL;

// How long we query entry points for.
const int kPossibleURLTimeScope = 30;

}  // anonymous namespace

// Contains the data needed to show a result.
struct PossibleURLModel::Result {
  Result() : index(0) {}

  GURL url;
  // Index of this Result in results_. This is used as the key into
  // favicon_map_ to lookup the favicon for the url, as well as the index
  // into results_ when the favicon is received.
  size_t index;
  ui::SortedDisplayURL display_url;
  std::wstring title;
};


PossibleURLModel::PossibleURLModel()
    : profile_(NULL),
      observer_(NULL) {
  if (!default_favicon) {
    ResourceBundle& rb = ResourceBundle::GetSharedInstance();
    default_favicon = rb.GetBitmapNamed(IDR_DEFAULT_FAVICON);
  }
}

PossibleURLModel::~PossibleURLModel() {
}

void PossibleURLModel::Reload(Profile *profile) {
  profile_ = profile;
  consumer_.CancelAllRequests();
  HistoryService* hs =
      profile->GetHistoryService(Profile::EXPLICIT_ACCESS);
  if (hs) {
    history::QueryOptions options;
    options.end_time = Time::Now();
    options.begin_time =
        options.end_time - TimeDelta::FromDays(kPossibleURLTimeScope);
    options.max_count = 50;

    hs->QueryHistory(string16(), options, &consumer_,
        NewCallback(this, &PossibleURLModel::OnHistoryQueryComplete));
  }
}

void PossibleURLModel::OnHistoryQueryComplete(HistoryService::Handle h,
                                              history::QueryResults* result) {
  results_.resize(result->size());
  std::string languages = profile_ ?
      profile_->GetPrefs()->GetString(prefs::kAcceptLanguages) : std::string();
  for (size_t i = 0; i < result->size(); ++i) {
    results_[i].url = (*result)[i].url();
    results_[i].index = i;
    results_[i].display_url =
        ui::SortedDisplayURL((*result)[i].url(), languages);
    results_[i].title = UTF16ToWide((*result)[i].title());
  }

  // The old version of this code would filter out all but the most recent
  // visit to each host, plus all typed URLs and AUTO_BOOKMARK transitions. I
  // think this dialog has a lot of work, and I'm not sure those old
  // conditions are correct (the results look about equal quality for my
  // history with and without those conditions), so I'm not spending time
  // re-implementing them here. They used to be implemented in the history
  // service, but I think they should be implemented here because that was
  // pretty specific behavior that shouldn't be generally exposed.

  favicon_map_.clear();
  if (observer_)
    observer_->OnModelChanged();
}

int PossibleURLModel::RowCount() {
  return static_cast<int>(results_.size());
}

const GURL& PossibleURLModel::GetURL(int row) {
  if (row < 0 || row >= RowCount()) {
    NOTREACHED();
    return GURL::EmptyGURL();
  }
  return results_[row].url;
}

const std::wstring& PossibleURLModel::GetTitle(int row) {
  if (row < 0 || row >= RowCount()) {
    NOTREACHED();
    return EmptyWString();
  }
  return results_[row].title;
}

string16 PossibleURLModel::GetText(int row, int col_id) {
  if (row < 0 || row >= RowCount()) {
    NOTREACHED();
    return string16();
  }

  if (col_id == IDS_ASI_PAGE_COLUMN) {
    string16 title = WideToUTF16Hack(GetTitle(row));
    // TODO(xji): Consider adding a special case if the title text is a URL,
    // since those should always have LTR directionality. Please refer to
    // http://crbug.com/6726 for more information.
    base::i18n::AdjustStringForLocaleDirection(&title);
    return title;
  }

  // TODO(brettw): this should probably pass the GURL up so the URL elider
  // can be used at a higher level when we know the width.
  string16 url = results_[row].display_url.display_url();
  return base::i18n::GetDisplayStringInLTRDirectionality(url);
}

SkBitmap PossibleURLModel::GetIcon(int row) {
  if (row < 0 || row >= RowCount()) {
    NOTREACHED();
    return *default_favicon;
  }

  Result& result = results_[row];
  FaviconMap::iterator i = favicon_map_.find(result.index);
  if (i != favicon_map_.end()) {
    // We already requested the favicon, return it.
    if (!i->second.isNull())
      return i->second;
  } else if (profile_) {
    FaviconService* favicon_service =
        profile_->GetFaviconService(Profile::EXPLICIT_ACCESS);
    if (favicon_service) {
      CancelableRequestProvider::Handle h =
          favicon_service->GetFaviconForURL(
              result.url, history::FAVICON, &consumer_,
              NewCallback(this, &PossibleURLModel::OnFaviconAvailable));
      consumer_.SetClientData(favicon_service, h, result.index);
      // Add an entry to the map so that we don't attempt to request the
      // favicon again.
      favicon_map_[result.index] = SkBitmap();
    }
  }
  return *default_favicon;
}

int PossibleURLModel::CompareValues(int row1, int row2, int column_id) {
  if (column_id == IDS_ASI_URL_COLUMN) {
    return results_[row1].display_url.Compare(
        results_[row2].display_url, GetCollator());
  }
  return ui::TableModel::CompareValues(row1, row2, column_id);
}

void PossibleURLModel::OnFaviconAvailable(
    FaviconService::Handle h,
    history::FaviconData favicon) {
  if (profile_) {
    FaviconService* favicon_service =
        profile_->GetFaviconService(Profile::EXPLICIT_ACCESS);
    size_t index = consumer_.GetClientData(favicon_service, h);
    if (favicon.is_valid()) {
      // The decoder will leave our bitmap empty on error.
      gfx::PNGCodec::Decode(favicon.image_data->front(),
                            favicon.image_data->size(),
                            &(favicon_map_[index]));

      // Notify the observer.
      if (!favicon_map_[index].isNull() && observer_)
        observer_->OnItemsChanged(static_cast<int>(index), 1);
    }
  }
}

void PossibleURLModel::SetObserver(ui::TableModelObserver* observer) {
  observer_ = observer;
}
