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

#include <math.h>

#include "type_conversion.h"

#include <QtCore/QCoreApplication>
#include <QtCore/QMetaObject>
#include <QtCore/QThread>
#include <QtPositioning/QGeoPositionInfoSource>

#include "base/bind.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "content/public/browser/browser_thread.h"
#include "services/device/geolocation/geolocation_provider.h"
#include "services/device/geolocation/geolocation_provider_impl.h"

namespace QtWebEngineCore {

using content::BrowserThread;

class QtPositioningHelper : public QObject {
    Q_OBJECT
public:
    QtPositioningHelper(LocationProviderQt *provider);
    ~QtPositioningHelper();

    Q_INVOKABLE void start(bool highAccuracy);
    Q_INVOKABLE void stop();
    Q_INVOKABLE void refresh();

private Q_SLOTS:
    void updatePosition(const QGeoPositionInfo &);
    void error(QGeoPositionInfoSource::Error positioningError);
    void timeout();

private:
    LocationProviderQt *m_locationProvider;
    QGeoPositionInfoSource *m_positionInfoSource;
    base::WeakPtrFactory<LocationProviderQt> m_locationProviderFactory;

    void postToLocationProvider(const base::Closure &task);
    friend class LocationProviderQt;
};

QtPositioningHelper::QtPositioningHelper(LocationProviderQt *provider)
    : m_locationProvider(provider)
    , m_positionInfoSource(0)
    , m_locationProviderFactory(provider)
{
    Q_ASSERT(provider);
}

QtPositioningHelper::~QtPositioningHelper()
{
}

static bool isHighAccuracySource(const QGeoPositionInfoSource *source)
{
    return source->supportedPositioningMethods().testFlag(
                QGeoPositionInfoSource::SatellitePositioningMethods);
}

void QtPositioningHelper::start(bool highAccuracy)
{
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    if (!m_positionInfoSource)
        m_positionInfoSource = QGeoPositionInfoSource::createDefaultSource(this);
    if (!m_positionInfoSource) {
        qWarning("Failed to initialize location provider: The system either has no default "
                 "position source, no valid plugins could be found or the user does not have "
                 "the right permissions.");
        error(QGeoPositionInfoSource::UnknownSourceError);
        return;
    }

    // Find high accuracy source if the default source is not already one.
    if (highAccuracy && !isHighAccuracySource(m_positionInfoSource)) {
        const QStringList availableSources = QGeoPositionInfoSource::availableSources();
        for (const QString &name : availableSources) {
            if (name == m_positionInfoSource->sourceName())
                continue;
            QGeoPositionInfoSource *source = QGeoPositionInfoSource::createSource(name, this);
            if (source && isHighAccuracySource(source)) {
                delete m_positionInfoSource;
                m_positionInfoSource = source;
                break;
            }
            delete source;
        }
        m_positionInfoSource->setPreferredPositioningMethods(
                    QGeoPositionInfoSource::SatellitePositioningMethods);
    }

    connect(m_positionInfoSource, &QGeoPositionInfoSource::positionUpdated, this, &QtPositioningHelper::updatePosition);
    // disambiguate the error getter and the signal in QGeoPositionInfoSource.
    connect(m_positionInfoSource, static_cast<void (QGeoPositionInfoSource::*)(QGeoPositionInfoSource::Error)>(&QGeoPositionInfoSource::error)
            , this, &QtPositioningHelper::error);
    connect(m_positionInfoSource, &QGeoPositionInfoSource::updateTimeout, this, &QtPositioningHelper::timeout);

    m_positionInfoSource->startUpdates();
    return;
}

void QtPositioningHelper::stop()
{
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    if (!m_positionInfoSource)
        return;
    m_positionInfoSource->stopUpdates();
}

void QtPositioningHelper::refresh()
{
    DCHECK_CURRENTLY_ON(BrowserThread::UI);
    if (!m_positionInfoSource)
        return;
    m_positionInfoSource->stopUpdates();
}

void QtPositioningHelper::updatePosition(const QGeoPositionInfo &pos)
{
    if (!pos.isValid())
        return;
    Q_ASSERT(m_positionInfoSource->error() == QGeoPositionInfoSource::NoError);
    device::mojom::Geoposition newPos;
    newPos.error_code = device::mojom::Geoposition::ErrorCode::NONE;
    newPos.error_message.clear();

    newPos.timestamp = toTime(pos.timestamp());
    newPos.latitude = pos.coordinate().latitude();
    newPos.longitude = pos.coordinate().longitude();

    const double altitude = pos.coordinate().altitude();
    if (!qIsNaN(altitude))
        newPos.altitude = altitude;

    // Chromium's geoposition needs a valid (as in >=0.) accuracy field.
    // try and get an accuracy estimate from QGeoPositionInfo.
    // If we don't have any accuracy info, 100m seems a pesimistic enough default.
    if (!pos.hasAttribute(QGeoPositionInfo::VerticalAccuracy) && !pos.hasAttribute(QGeoPositionInfo::HorizontalAccuracy))
        newPos.accuracy = 100;
    else {
        const double vAccuracy = pos.hasAttribute(QGeoPositionInfo::VerticalAccuracy) ? pos.attribute(QGeoPositionInfo::VerticalAccuracy) : 0;
        const double hAccuracy = pos.hasAttribute(QGeoPositionInfo::HorizontalAccuracy) ? pos.attribute(QGeoPositionInfo::HorizontalAccuracy) : 0;
        newPos.accuracy = sqrt(vAccuracy * vAccuracy + hAccuracy * hAccuracy);
    }

    // And now the "nice to have" fields (-1 means invalid).
    newPos.speed =  pos.hasAttribute(QGeoPositionInfo::GroundSpeed) ? pos.attribute(QGeoPositionInfo::GroundSpeed) : -1;
    newPos.heading =  pos.hasAttribute(QGeoPositionInfo::Direction) ? pos.attribute(QGeoPositionInfo::Direction) : -1;

    if (m_locationProvider)
        postToLocationProvider(base::Bind(&LocationProviderQt::updatePosition, m_locationProviderFactory.GetWeakPtr(), newPos));
}

void QtPositioningHelper::error(QGeoPositionInfoSource::Error positioningError)
{
    Q_ASSERT(positioningError != QGeoPositionInfoSource::NoError);
    device::mojom::Geoposition newPos;
    switch (positioningError) {
    case QGeoPositionInfoSource::AccessError:
        newPos.error_code = device::mojom::Geoposition::ErrorCode::PERMISSION_DENIED;
        break;
    case QGeoPositionInfoSource::ClosedError:
    case QGeoPositionInfoSource::UnknownSourceError: // position unavailable is as good as it gets in Geoposition
    default:
        newPos.error_code = device::mojom::Geoposition::ErrorCode::POSITION_UNAVAILABLE;
        break;
    }
    if (m_locationProvider)
        postToLocationProvider(base::Bind(&LocationProviderQt::updatePosition, m_locationProviderFactory.GetWeakPtr(), newPos));
}

void QtPositioningHelper::timeout()
{
    device::mojom::Geoposition newPos;
    // content::Geoposition::ERROR_CODE_TIMEOUT is not handled properly in the renderer process, and the timeout
    // argument used in JS never comes all the way to the browser process.
    // Let's just treat it like any other error where the position is unavailable.
    newPos.error_code = device::mojom::Geoposition::ErrorCode::POSITION_UNAVAILABLE;
    if (m_locationProvider)
        postToLocationProvider(base::Bind(&LocationProviderQt::updatePosition, m_locationProviderFactory.GetWeakPtr(), newPos));
}

inline void QtPositioningHelper::postToLocationProvider(const base::Closure &task)
{
    static_cast<device::GeolocationProviderImpl*>(device::GeolocationProvider::GetInstance())->task_runner()->PostTask(FROM_HERE, task);
}

LocationProviderQt::LocationProviderQt()
    : m_positioningHelper(0)
{
}

LocationProviderQt::~LocationProviderQt()
{
    if (m_positioningHelper) {
        m_positioningHelper->m_locationProvider = 0;
        m_positioningHelper->m_locationProviderFactory.InvalidateWeakPtrs();
        m_positioningHelper->deleteLater();
    }
}

void LocationProviderQt::StartProvider(bool highAccuracy)
{
    QThread *guiThread = qApp->thread();
    if (!m_positioningHelper) {
        m_positioningHelper = new QtPositioningHelper(this);
        m_positioningHelper->moveToThread(guiThread);
    }

    QMetaObject::invokeMethod(m_positioningHelper, "start", Qt::QueuedConnection, Q_ARG(bool, highAccuracy));
}

void LocationProviderQt::StopProvider()
{
    if (m_positioningHelper)
        QMetaObject::invokeMethod(m_positioningHelper, "stop", Qt::QueuedConnection);
}

void LocationProviderQt::OnPermissionGranted()
{
    if (m_positioningHelper)
        QMetaObject::invokeMethod(m_positioningHelper, "refresh", Qt::QueuedConnection);
}

void LocationProviderQt::SetUpdateCallback(const LocationProviderUpdateCallback& callback)
{
    m_callback = callback;
}

void LocationProviderQt::updatePosition(const device::mojom::Geoposition &position)
{
    m_lastKnownPosition = position;
    m_callback.Run(this, position);
}

} // namespace QtWebEngineCore

#include "location_provider_qt.moc"
