/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWebEngine module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "favicon_manager.h"
#include "type_conversion.h"
#include "web_contents_adapter_client.h"
#include "web_engine_settings.h"

#include "base/bind.h"
#include "content/public/browser/favicon_status.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/url_constants.h"
#include "net/base/data_url.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkPixelRef.h"
#include "ui/gfx/geometry/size.h"

namespace QtWebEngineCore {

static inline bool isResourceUrl(const QUrl &url)
{
    return !url.scheme().compare(QLatin1String("qrc"));
}

static inline bool isDataUrl(const QUrl &url)
{
    return !url.scheme().compare(QLatin1String(url::kDataScheme));
}

static inline unsigned area(const QSize &size)
{
    return size.width() * size.height();
}


FaviconManager::FaviconManager(content::WebContents *webContents, WebContentsAdapterClient *viewClient)
    : m_webContents(webContents)
    , m_viewClient(viewClient)
    , m_candidateCount(0)
    , m_weakFactory(new base::WeakPtrFactory<FaviconManager>(this))
{
}

FaviconManager::~FaviconManager()
{
}

int FaviconManager::downloadIcon(const QUrl &url)
{
    static const uint32_t maxSize = 256;
    static int fakeId = 0;
    int id;

    bool cached = m_icons.contains(url);
    if (isResourceUrl(url) || isDataUrl(url) || cached) {
        id = --fakeId;
        m_pendingRequests.insert(id, url);
    } else {
        id = m_webContents->DownloadImage(
             toGurl(url),
             true, // is_favicon
             0, // preferred_size
             maxSize,
             false, // normal cache policy
             base::Bind(&FaviconManager::iconDownloadFinished, m_weakFactory->GetWeakPtr()));
    }

    Q_ASSERT(!m_inProgressRequests.contains(id));
    m_inProgressRequests.insert(id, url);

    return id;
}

void FaviconManager::iconDownloadFinished(int id,
                                                 int status,
                                                 const GURL &url,
                                                 const std::vector<SkBitmap> &bitmaps,
                                                 const std::vector<gfx::Size> &original_bitmap_sizes)
{
    Q_UNUSED(status);
    Q_UNUSED(url);
    Q_UNUSED(original_bitmap_sizes);

    storeIcon(id, toQIcon(bitmaps));
}

/* Pending requests are used to mark icons that are already downloaded (cached icons or icons
 * stored in qrc). These requests are also stored in the m_inProgressRequests but the corresponding
 * icons are stored in m_icons explicitly by this function. It is necessary to avoid
 * m_inProgressRequests being emptied right before the next icon is added by a downloadIcon() call.
 */
void FaviconManager::downloadPendingRequests()
{
    for (auto it = m_pendingRequests.cbegin(), end = m_pendingRequests.cend(); it != end; ++it) {
        QIcon icon;

        QUrl requestUrl = it.value();
        if (!m_icons.contains(requestUrl)) {
            if (isResourceUrl(requestUrl)) {
                icon = QIcon(requestUrl.toString().remove(0, 3));
            } else if (isDataUrl(requestUrl)) {
                std::string mime_type, char_set, data;
                if (net::DataURL::Parse(toGurl(requestUrl), &mime_type, &char_set, &data) && !data.empty()) {
                    const unsigned char *src_data = reinterpret_cast<const unsigned char *>(data.data());
                    QImage image = QImage::fromData(src_data, data.size());
                    icon.addPixmap(QPixmap::fromImage(image).copy());
                }
            }
        }

        storeIcon(it.key(), icon);
    }

    m_pendingRequests.clear();
}

void FaviconManager::storeIcon(int id, const QIcon &icon)
{

    // Icon download has been interrupted
    if (!m_inProgressRequests.contains(id))
        return;

    QUrl requestUrl = m_inProgressRequests[id];
    FaviconInfo &faviconInfo = m_faviconInfoMap[requestUrl];

    unsigned iconCount = 0;
    if (!icon.isNull())
        iconCount = icon.availableSizes().count();

    if (iconCount > 0) {
        m_icons.insert(requestUrl, icon);

        faviconInfo.size = icon.availableSizes().at(0);
        if (iconCount > 1) {
            faviconInfo.multiSize = true;
            unsigned bestArea = area(faviconInfo.size);
            for (unsigned i = 1; i < iconCount; ++i) {
                QSize iconSize = icon.availableSizes().at(i);
                if (bestArea < area(iconSize)) {
                    faviconInfo.size = iconSize;
                    bestArea = area(iconSize);
                }
            }
        }
    } else if (id >= 0) {
        // Reset size if icon cannot be downloaded
        faviconInfo.size = QSize(0, 0);
    }

    m_inProgressRequests.remove(id);
    if (m_inProgressRequests.isEmpty()) {
        WebEngineSettings *settings = m_viewClient->webEngineSettings();
        bool touchIconsEnabled = settings->testAttribute(WebEngineSettings::TouchIconsEnabled);

        generateCandidateIcon(touchIconsEnabled);
        const QUrl &iconUrl = candidateIconUrl(touchIconsEnabled);
        propagateIcon(iconUrl);
    }
}

void FaviconManager::propagateIcon(const QUrl &iconUrl) const
{
    content::NavigationEntry *entry = m_webContents->GetController().GetVisibleEntry();
    if (entry) {
        content::FaviconStatus &favicon = entry->GetFavicon();
        favicon.url = toGurl(iconUrl);
        favicon.valid = true;
    }

    m_viewClient->iconChanged(iconUrl);
}

QIcon FaviconManager::getIcon(const QUrl &url) const
{
    if (url.isEmpty())
        return m_candidateIcon;

    if (!m_icons.contains(url))
        return QIcon();

    return m_icons[url];
}

FaviconInfo FaviconManager::getFaviconInfo(const QUrl &url) const
{
    Q_ASSERT(m_faviconInfoMap.contains(url));
    return m_faviconInfoMap[url];
}

QList<FaviconInfo> FaviconManager::getFaviconInfoList(bool candidatesOnly) const
{
    QList<FaviconInfo> faviconInfoList = m_faviconInfoMap.values();

    if (candidatesOnly) {
        const auto hasNoCandidate = [](const FaviconInfo &info) { return !info.candidate; };
        faviconInfoList.erase(std::remove_if(faviconInfoList.begin(), faviconInfoList.end(),
                                             hasNoCandidate),
                              faviconInfoList.end());
    }

    return faviconInfoList;
}

void FaviconManager::update(const QList<FaviconInfo> &candidates)
{
    updateCandidates(candidates);

    WebEngineSettings *settings = m_viewClient->webEngineSettings();
    if (!settings->testAttribute(WebEngineSettings::AutoLoadIconsForPage)) {
        m_viewClient->iconChanged(QUrl());
        return;
    }

    bool touchIconsEnabled = settings->testAttribute(WebEngineSettings::TouchIconsEnabled);

    const QList<FaviconInfo> &faviconInfoList = getFaviconInfoList(true /* candidates only */);
    for (auto it = faviconInfoList.cbegin(), end = faviconInfoList.cend(); it != end; ++it) {
        if (!touchIconsEnabled && !(it->type & FaviconInfo::Favicon))
            continue;

        if (it->isValid())
            downloadIcon(it->url);
    }

    downloadPendingRequests();

    // Reset icon if nothing was downloaded
    if (m_inProgressRequests.isEmpty()) {
        content::NavigationEntry *entry = m_webContents->GetController().GetVisibleEntry();
        if (entry && !entry->GetFavicon().valid)
            m_viewClient->iconChanged(QUrl());
    }
}

void FaviconManager::updateCandidates(const QList<FaviconInfo> &candidates)
{
    // Invalidate types of the already stored candidate icons because it might differ
    // among pages.
    for (FaviconInfo candidateFaviconInfo : candidates) {
        const QUrl &candidateUrl = candidateFaviconInfo.url;
        if (m_faviconInfoMap.contains(candidateUrl))
            m_faviconInfoMap[candidateUrl].type = FaviconInfo::InvalidIcon;
    }

    m_candidateCount = candidates.count();
    for (FaviconInfo candidateFaviconInfo : candidates) {
        const QUrl &candidateUrl = candidateFaviconInfo.url;

        if (!m_faviconInfoMap.contains(candidateUrl))
            m_faviconInfoMap.insert(candidateUrl, candidateFaviconInfo);
        else {
            // The same icon URL can be used for different types.
            m_faviconInfoMap[candidateUrl].type |= candidateFaviconInfo.type;
        }

        m_faviconInfoMap[candidateUrl].candidate = true;
    }
}

void FaviconManager::resetCandidates()
{
    // Interrupt in progress icon downloads
    m_pendingRequests.clear();
    m_inProgressRequests.clear();

    m_candidateCount = 0;
    m_candidateIcon = QIcon();
    for (auto it = m_faviconInfoMap.begin(), end = m_faviconInfoMap.end(); it != end; ++it)
        it->candidate = false;
}

bool FaviconManager::hasCandidate() const
{
    return (m_candidateCount > 0);
}

QUrl FaviconManager::candidateIconUrl(bool touchIconsEnabled) const
{
    QUrl iconUrl;
    const QList<FaviconInfo> &faviconInfoList = getFaviconInfoList(true /* candidates only */);

    unsigned bestArea = 0;
    for (auto it = faviconInfoList.cbegin(), end = faviconInfoList.cend(); it != end; ++it) {
        if (!touchIconsEnabled && !(it->type & FaviconInfo::Favicon))
            continue;

        if (it->isValid() && bestArea < area(it->size)) {
            iconUrl = it->url;
            bestArea = area(it->size);
        }
    }

    return iconUrl;
}

void FaviconManager::generateCandidateIcon(bool touchIconsEnabled)
{
    Q_ASSERT(m_candidateCount);

    m_candidateIcon = QIcon();
    const QList<FaviconInfo> &faviconInfoList = getFaviconInfoList(true /* candidates only */);

    for (auto it = faviconInfoList.cbegin(), end = faviconInfoList.cend(); it != end; ++it) {
        if (!touchIconsEnabled && !(it->type & FaviconInfo::Favicon))
            continue;

        if (!it->isValid() || !it->isDownloaded())
            continue;

        const QIcon &icon = getIcon(it->url);

        if (!it->multiSize) {
            if (!m_candidateIcon.availableSizes().contains(it->size))
                m_candidateIcon.addPixmap(icon.pixmap(it->size));

            continue;
        }

        const auto sizes = icon.availableSizes();
        for (const QSize &size : sizes) {
            if (!m_candidateIcon.availableSizes().contains(size))
                m_candidateIcon.addPixmap(icon.pixmap(size));
        }
    }
}

void FaviconManager::copyStateFrom(FaviconManager *source)
{
    m_faviconInfoMap = source->m_faviconInfoMap;
    m_icons = source->m_icons;
}

FaviconInfo::FaviconInfo()
    : url(QUrl())
    , type(FaviconInfo::InvalidIcon)
    , size(QSize(0, 0))
    , candidate(false)
    , multiSize(false)
{
}

FaviconInfo::FaviconInfo(const FaviconInfo &other)
    : url(other.url)
    , type(other.type)
    , size(other.size)
    , candidate(other.candidate)
    , multiSize(other.multiSize)
{
}

FaviconInfo::FaviconInfo(const QUrl &url, FaviconInfo::FaviconTypeFlags type)
    : url(url)
    , type(type)
    , size(QSize(0, 0))
    , candidate(false)
    , multiSize(false)
{
}

FaviconInfo::~FaviconInfo()
{
}

bool FaviconInfo::isValid() const
{
    if (type == FaviconInfo::InvalidIcon)
        return false;

    if (url.isEmpty() || !url.isValid())
        return false;

    return true;
}

bool FaviconInfo::isDownloaded() const
{
    return area(size) > 0;
}

} // namespace QtWebEngineCore
