// 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 "components/history/core/browser/android/favicon_sql_handler.h"

#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/memory/ref_counted_memory.h"
#include "base/stl_util.h"
#include "components/history/core/browser/thumbnail_database.h"

using base::Time;

namespace history {

namespace {

// The interesting columns of this handler.
const HistoryAndBookmarkRow::ColumnID kInterestingColumns[] = {
  HistoryAndBookmarkRow::FAVICON};

}  // namespace

FaviconSQLHandler::FaviconSQLHandler(ThumbnailDatabase* thumbnail_db)
    : SQLHandler(kInterestingColumns, base::size(kInterestingColumns)),
      thumbnail_db_(thumbnail_db) {}

FaviconSQLHandler::~FaviconSQLHandler() {
}

bool FaviconSQLHandler::Update(const HistoryAndBookmarkRow& row,
                               const TableIDRows& ids_set) {
  if (!row.favicon_valid())
    return Delete(ids_set);

  // If the image_data will be updated, it is not reasonable to find if the
  // icon is already in database, just create a new favicon.
  // TODO(pkotwicz): Pass in real pixel size.
  favicon_base::FaviconID favicon_id = thumbnail_db_->AddFavicon(
      GURL(), favicon_base::IconType::kFavicon, row.favicon(),
      FaviconBitmapType::ON_VISIT, Time::Now(), gfx::Size());

  if (!favicon_id)
    return false;

  std::vector<favicon_base::FaviconID> favicon_ids;
  for (TableIDRows::const_iterator i = ids_set.begin();
       i != ids_set.end(); ++i) {
    // Remove all icon mappings to favicons of type kFavicon.
    std::vector<IconMapping> icon_mappings;
    thumbnail_db_->GetIconMappingsForPageURL(
        i->url, {favicon_base::IconType::kFavicon}, &icon_mappings);
    for (std::vector<IconMapping>::const_iterator m = icon_mappings.begin();
         m != icon_mappings.end(); ++m) {
      if (!thumbnail_db_->DeleteIconMapping(m->mapping_id))
        return false;

      // Keep the old icon for deleting it later if possible.
      favicon_ids.push_back(m->icon_id);
    }
    // Add the icon mapping.
    if (!thumbnail_db_->AddIconMapping(i->url, favicon_id))
      return false;
  }
  // As we update the favicon, Let's remove unused favicons if any.
  if (!favicon_ids.empty() && !DeleteUnusedFavicon(favicon_ids))
    return false;

  return true;
}

bool FaviconSQLHandler::Delete(const TableIDRows& ids_set) {
  std::vector<favicon_base::FaviconID> favicon_ids;
  for (TableIDRows::const_iterator i = ids_set.begin();
       i != ids_set.end(); ++i) {
    // Since the URL was deleted, we delete all types of icon mappings.
    std::vector<IconMapping> icon_mappings;
    thumbnail_db_->GetIconMappingsForPageURL(i->url, &icon_mappings);
    for (std::vector<IconMapping>::const_iterator m = icon_mappings.begin();
         m != icon_mappings.end(); ++m) {
      favicon_ids.push_back(m->icon_id);
    }
    if (!thumbnail_db_->DeleteIconMappings(i->url))
      return false;
  }

  if (favicon_ids.empty())
    return true;

  if (!DeleteUnusedFavicon(favicon_ids))
    return false;

  return true;
}

bool FaviconSQLHandler::Insert(HistoryAndBookmarkRow* row) {
  if (!row->is_value_set_explicitly(HistoryAndBookmarkRow::FAVICON) ||
      !row->favicon_valid())
    return true;

  DCHECK(row->is_value_set_explicitly(HistoryAndBookmarkRow::URL));

  // Is it a problem to give a empty URL?
  // TODO(pkotwicz): Pass in real pixel size.
  favicon_base::FaviconID id = thumbnail_db_->AddFavicon(
      GURL(), favicon_base::IconType::kFavicon, row->favicon(),
      FaviconBitmapType::ON_VISIT, Time::Now(), gfx::Size());
  if (!id)
    return false;
  return thumbnail_db_->AddIconMapping(row->url(), id);
}

bool FaviconSQLHandler::DeleteUnusedFavicon(
    const std::vector<favicon_base::FaviconID>& ids) {
  for (std::vector<favicon_base::FaviconID>::const_iterator i = ids.begin();
       i != ids.end();
       ++i) {
    if (!thumbnail_db_->HasMappingFor(*i) && !thumbnail_db_->DeleteFavicon(*i))
      return false;
  }
  return true;
}

}  // namespace history.
