// Copyright (C) 2015 The Android Open Source Project
//
// This software is licensed under the terms of the GNU General Public
// License version 2, as published by the Free Software Foundation, and
// may be copied, distributed, and modified under those terms.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

#include "android/skin/qt/extended-pages/location-page.h"

#include "android/emulation/control/location_agent.h"
#include "android/gps/GpxParser.h"
#include "android/gps/KmlParser.h"
#include "android/metrics/MetricsReporter.h"
#include "android/metrics/proto/studio_stats.pb.h"
#include "android/settings-agent.h"
#include "android/skin/qt/error-dialog.h"
#include "android/skin/qt/extended-pages/common.h"
#include "android/skin/qt/qt-settings.h"

#include <QFileDialog>
#include <QSettings>
#include <unistd.h>

static const double kGplexLon = -122.084;
static const double kGplexLat =   37.422;

LocationPage::LocationPage(QWidget *parent) :
    QWidget(parent),
    mUi(new Ui::LocationPage),
    mNowLoadingGeoData(false),
    mGeoDataLoadingStopRequested(false)
{
    mUi->setupUi(this);
    mNowPlaying = false;
    mTimer.setSingleShot(true);

    // We can only send 1 decimal of altitude (in meters).
    mAltitudeValidator.setNotation(QDoubleValidator::StandardNotation);
    mAltitudeValidator.setRange(-1000, 10000, 1);
    mAltitudeValidator.setLocale(QLocale::C);
    mUi->loc_altitudeInput->setValidator(&mAltitudeValidator);

    mUi->loc_latitudeInput->setMinValue(-90.0);
    mUi->loc_latitudeInput->setMaxValue(90.0);
    QObject::connect(&mTimer, &QTimer::timeout, this, &LocationPage::timeout);
    QObject::connect(this, &LocationPage::locationUpdateRequired,
                     this, &LocationPage::updateDisplayedLocation);
    setButtonEnabled(mUi->loc_playStopButton, getSelectedTheme(), false);

    // Restore previous values. If there are no previous values, use the
    // Googleplex's longitude and latitude.
    QSettings settings;
    double altValue = settings.value(Ui::Settings::LOCATION_ENTERED_ALTITUDE, 0.0).toDouble();
    mUi->loc_altitudeInput->setText( QString::number(altValue, 'f', 1) );
    mUi->loc_longitudeInput->setValue(
            settings.value(Ui::Settings::LOCATION_ENTERED_LONGITUDE, kGplexLon).toDouble());
    mUi->loc_latitudeInput->setValue(
            settings.value(Ui::Settings::LOCATION_ENTERED_LATITUDE, kGplexLat).toDouble());
    mUi->loc_playbackSpeed->setCurrentIndex(
            settings.value(Ui::Settings::LOCATION_PLAYBACK_SPEED, 0).toInt());
    QString location_data_file =
        settings.value(Ui::Settings::LOCATION_PLAYBACK_FILE, "").toString();
    mUi->loc_pathTable->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
    mGeoDataLoader = GeoDataLoaderThread::newInstance(
            this,
            SLOT(geoDataThreadStarted()),
            SLOT(startupGeoDataThreadFinished(QString, bool, QString)));
    mGeoDataLoader->loadGeoDataFromFile(location_data_file, &mGpsFixesArray);

    using android::metrics::PeriodicReporter;
    mMetricsReportingToken = PeriodicReporter::get().addCancelableTask(
            60 * 10 * 1000,  // reporting period
            [this](android_studio::AndroidStudioEvent* event) {
                if (mLocationUsed) {
                    event->mutable_emulator_details()
                            ->mutable_used_features()
                            ->set_gps(true);
                    mMetricsReportingToken.reset();  // Report it only once.
                    return true;
                }
                return false;
    });
}

LocationPage::~LocationPage() {
    if (mGeoDataLoader != nullptr) {
        // If there's a loader thread running in the background,
        // ignore all signals from it and wait for it to finish.
        mGeoDataLoader->blockSignals(true);
        mGeoDataLoader->wait();
    }
}

void LocationPage::setLocationAgent(const QAndroidLocationAgent* agent) {
    mLocationAgent = agent;

    // Show the user the device's current location.
    double curLat, curLon, curAlt;
    getDeviceLocation(mLocationAgent, &curLat, &curLon, &curAlt);

    sendLocationToDevice(mLocationAgent, curLat, curLon, curAlt);

    // We cannot update the UI here because we are not called from
    // the Qt thread. Emit a signal to do that update.
    emit locationUpdateRequired(curLat, curLon, curAlt);
}

void LocationPage::on_loc_GpxKmlButton_clicked()
{
    // Use dialog to get file name
    QString fileName = QFileDialog::getOpenFileName(this, tr("Open GPX or KML File"), ".",
                                                    tr("GPX and KML files (*.gpx *.kml)"));

    if (fileName.isNull()) return;

    // Asynchronously parse the file with geo data.
    // If the file is big enough, parsing it synchronously will cause a noticeable
    // hiccup in the UI.
    mGeoDataLoader = GeoDataLoaderThread::newInstance(this,
                                                      SLOT(geoDataThreadStarted()),
                                                      SLOT(geoDataThreadFinished(QString, bool, QString)));
    mGeoDataLoader->loadGeoDataFromFile(fileName, &mGpsFixesArray);
}

void LocationPage::on_loc_pathTable_cellChanged(int row, int col)
{
    // If the cell's contents are bad, turn the cell red
    QString outErrorMessage;
    bool cellOK = validateCell(mUi->loc_pathTable, row, col, &outErrorMessage);
    QColor normalColor =
        getSelectedTheme() == SETTINGS_THEME_LIGHT ? Qt::black : Qt::white;
    QColor newColor = (cellOK ? normalColor : Qt::red);
    mUi->loc_pathTable->item(row, col)->setForeground(QBrush(newColor));
}

void LocationPage::on_loc_playStopButton_clicked() {
    mLocationUsed = true;
    if (mNowPlaying) {
        locationPlaybackStop();
    } else {
        locationPlaybackStart();
    }
}

void LocationPage::on_loc_modeSwitch_currentIndexChanged(int index) {
    if (index == 1) {
        mUi->loc_latitudeInput->setInputMode(AngleInputWidget::InputMode::Sexagesimal);
        mUi->loc_longitudeInput->setInputMode(AngleInputWidget::InputMode::Sexagesimal);
    } else {
        mUi->loc_latitudeInput->setInputMode(AngleInputWidget::InputMode::Decimal);
        mUi->loc_longitudeInput->setInputMode(AngleInputWidget::InputMode::Decimal);
    }
}

void LocationPage::on_loc_sendPointButton_clicked() {
    mLocationUsed = true;
    mUi->loc_latitudeInput->forceUpdate();
    mUi->loc_longitudeInput->forceUpdate();

    double altitude = mUi->loc_altitudeInput->text().toDouble();
    if (altitude < -1000.0 || altitude > 10000.0) {
        QSettings settings;
        mUi->loc_altitudeInput->setText(QString::number(
                settings.value(Ui::Settings::LOCATION_ENTERED_ALTITUDE, 0.0)
                        .toDouble()));
    }

    updateDisplayedLocation(mUi->loc_latitudeInput->value(),
                            mUi->loc_longitudeInput->value(),
                            mUi->loc_altitudeInput->text().toDouble());

    sendLocationToDevice(mLocationAgent,
                         mUi->loc_latitudeInput->value(),
                         mUi->loc_longitudeInput->value(),
                         mUi->loc_altitudeInput->text().toDouble());
}

void LocationPage::updateDisplayedLocation(double lat, double lon, double alt) {
    QString curLoc = tr("Longitude: %1\nLatitude: %2\nAltitude: %3")
                     .arg(lon, 0, 'f', 4).arg(lat, 0, 'f', 4).arg(alt, 0, 'f', 1);
    mUi->loc_currentLoc->setPlainText(curLoc);
}

void LocationPage::on_loc_longitudeInput_valueChanged(double value) {
    QSettings settings;
    settings.setValue(Ui::Settings::LOCATION_ENTERED_LONGITUDE, value);
}

void LocationPage::on_loc_latitudeInput_valueChanged(double value) {
    QSettings settings;
    settings.setValue(Ui::Settings::LOCATION_ENTERED_LATITUDE, value);
}

void LocationPage::on_loc_altitudeInput_editingFinished() {
    QSettings settings;
    settings.setValue(Ui::Settings::LOCATION_ENTERED_ALTITUDE,
                      mUi->loc_altitudeInput->text().toDouble());
}

void LocationPage::on_loc_playbackSpeed_currentIndexChanged(int index) {
    QSettings settings;
    settings.setValue(Ui::Settings::LOCATION_PLAYBACK_SPEED, index);
}

bool LocationPage::validateCell(QTableWidget* table,
                                int row,
                                int col,
                                QString* outErrorMessage) {
    QTableWidgetItem *theItem;
    double cellValue;
    bool cellOK = true;

    // The entry is a number. Check its range.
    switch (col) {
        case 0: // Delay
            theItem = table->item(row, col);
            cellValue = theItem->text().toDouble(&cellOK); // Sets 'cellOK'
            if (!cellOK) {
                *outErrorMessage = tr("Delay must be a number.");
                return false;
            }
            // Except for the first entry, the delay must be >= 1 millisecond
            if (row != 0 && cellValue < 0.001) {
                *outErrorMessage =
                        tr("Delay must be >= 1 millisecond with the exception "
                           "of the first entry.");
                cellOK = false;
            }
            break;
        case 1: // Latitude
            theItem = table->item(row, col);
            cellValue = theItem->text().toDouble(&cellOK); // Sets 'cellOK'
            if (!cellOK) {
                *outErrorMessage = tr("Latitude must be a number.");
                return false;
            }
            if (cellValue < -90.0 || cellValue > 90.0) {
                *outErrorMessage =
                        tr("Latitude must be between -90 and 90, inclusive.");
                cellOK = false;
            }
            break;
        case 2: // Longitude
            theItem = table->item(row, col);
            cellValue = theItem->text().toDouble(&cellOK); // Sets 'cellOK'
            if (!cellOK) {
                *outErrorMessage = tr("Longitude must be a number.");
                return false;
            }
            if (cellValue < -180.0 || cellValue > 180.0) {
                *outErrorMessage = tr(
                        "Longitude must be between -180 and 180, inclusive.");
                cellOK = false;
            }
            break;
        case 3: // Elevation
            theItem = table->item(row, col);
            cellValue = theItem->text().toDouble(&cellOK); // Sets 'cellOK'
            if (!cellOK) {
                *outErrorMessage = tr("Elevation must be a number.");
                return false;
            }
            if (cellValue < -1000.0 || cellValue > 10000.0) {
                *outErrorMessage = tr(
                        "Altitude must be between -1000 and 10000, inclusive.");
                cellOK = false;
            }
            break;
        default:
            // Name, description: Anything is OK
            cellOK = true;
            break;
    }
    return cellOK;
}


static QTableWidgetItem* itemForTable(const QString& text) {
    QTableWidgetItem* item = new QTableWidgetItem(text);
    item->setTextAlignment(Qt::AlignRight | Qt::AlignVCenter);
    return item;
}

void LocationPage::populateTable(GpsFixArray* fixes)
{
    // Delete all rows in table
    mUi->loc_pathTable->setRowCount(0);

    if (fixes->size() > 0) {
        // Special case, the first row will have delay 0
        time_t previousTime = fixes->at(0).time;
        mUi->loc_pathTable->setRowCount(fixes->size());
        mUi->loc_pathTable->blockSignals(true);
        for (unsigned i = 0; !mGeoDataLoadingStopRequested && i < fixes->size(); i++) {
            GpsFix &fix = fixes->at(i);
            time_t delay = fix.time - previousTime; // In seconds

            // Ensure all other delays are > 0, even if multiple points have the same timestamp
            if (delay == 0 && i != 0) {
                delay = 2;
            }

            mUi->loc_pathTable->setItem(i, 0, itemForTable(QString::number(delay)));
            mUi->loc_pathTable->setItem(i, 1, itemForTable(QString::number(fix.latitude)));
            mUi->loc_pathTable->setItem(i, 2, itemForTable(QString::number(fix.longitude)));
            mUi->loc_pathTable->setItem(i, 3, itemForTable(QString::number(fix.elevation)));
            mUi->loc_pathTable->setItem(i, 4, itemForTable(QString::fromStdString(fix.name)));
            mUi->loc_pathTable->setItem(i, 5, itemForTable(QString::fromStdString(fix.description)));

            // If the fixes array contains a lot of elements, this loop can cause
            // a lag in the UI. Just make sure we let the application handle UI
            // events for every few rows we add.
            if (i % 100 == 0) {
                qApp->processEvents();
            }
            previousTime = fix.time;
        }
        mUi->loc_pathTable->blockSignals(false);
        setButtonEnabled(mUi->loc_playStopButton, getSelectedTheme(), true);
    } else {
        setButtonEnabled(mUi->loc_playStopButton, getSelectedTheme(), false);
    }
}

void LocationPage::locationPlaybackStart()
{
    if (mUi->loc_pathTable->rowCount() <= 0) {
        return;
    }

    // Validate all the values in the table.
    QString outErrorMessage;
    for (int row = 0; row < mUi->loc_pathTable->rowCount(); row++) {
        for (int col = 0; col < mUi->loc_pathTable->columnCount(); col++) {
            if (!validateCell(mUi->loc_pathTable, row, col, &outErrorMessage)) {
                mUi->loc_pathTable->setCurrentCell(row, col);
                showErrorDialog(tr("The table contains errors.No locations "
                                   "were sent.<br/>Error: %1")
                                        .arg(outErrorMessage),
                                tr("GPS Playback"));
                return;
            }
        }
    }

    mRowToSend = std::max(0, mUi->loc_pathTable->currentRow());

    SettingsTheme theme = getSelectedTheme();

    // Disable editing the data in the table while playback is in progress.
    mUi->loc_pathTable->setEditTriggers(QAbstractItemView::NoEditTriggers);

    // Disable loading a new dataset while playback is in progress.
    setButtonEnabled(mUi->loc_GpxKmlButton,  theme, false);

    // Change the icon on the play/stop button.
    mUi->loc_playStopButton->setIcon(getIconForCurrentTheme("stop"));
    mUi->loc_playStopButton->setProperty("themeIconName", "stop");


    // The timer will be triggered for the first row after this
    // function returns.
    mTimer.setInterval(0);
    mTimer.start();
    mNowPlaying = true;
}

void LocationPage::locationPlaybackStop()
{
    mTimer.stop();
    if (mRowToSend > 0 &&
        mRowToSend <= mUi->loc_pathTable->rowCount()) {
        if (mRowToSend == mUi->loc_pathTable->rowCount()) {
            mUi->loc_pathTable->setCurrentItem(nullptr);
        }
        mUi->loc_pathTable->item(mRowToSend - 1, 0)->setIcon(QIcon());
    }
    mRowToSend = -1;
    SettingsTheme theme = getSelectedTheme();
    setButtonEnabled(mUi->loc_GpxKmlButton,  theme, true);
    mUi->loc_playStopButton->setIcon(getIconForCurrentTheme("play_arrow"));
    mUi->loc_playStopButton->setProperty("themeIconName", "play_arrow");
    mUi->loc_pathTable->setEditTriggers(QAbstractItemView::DoubleClicked |
                                                QAbstractItemView::EditKeyPressed |
                                                QAbstractItemView::AnyKeyPressed);
    mNowPlaying = false;
}


void LocationPage::timeout() {
    bool cellOK;
    QTableWidgetItem *theItem;

    // Check if we've reached the end of the dataset.
    if (mRowToSend < 0  ||
        mRowToSend >= mUi->loc_pathTable->rowCount()) {
        // No more to send. Same as clicking Stop.
        locationPlaybackStop();
        return;
    }

    // Get the data for the point we're about to send.
    theItem = mUi->loc_pathTable->item(mRowToSend, 1);
    double lat = theItem->text().toDouble(&cellOK);
    theItem = mUi->loc_pathTable->item(mRowToSend, 2);
    double lon = theItem->text().toDouble(&cellOK);
    theItem = mUi->loc_pathTable->item(mRowToSend, 3);
    double alt = theItem->text().toDouble(&cellOK);

    // Update the appearance of the table:
    // 1. Clear the "play arrow" icon from the previous point, if necessary.
    // 2. Set the "play arrow" icon near the point we're about to send.
    // 3. Scroll to the point that is being sent.
    // 4. Make it selected.
    if (mRowToSend > 0) {
        mUi->loc_pathTable->item(mRowToSend - 1, 0)->setIcon(QIcon());
    }
    QTableWidgetItem* currentItem = mUi->loc_pathTable->item(mRowToSend, 0);
    currentItem->setIcon(getIconForCurrentTheme("play_arrow"));
    mUi->loc_pathTable->scrollToItem(currentItem);
    mUi->loc_pathTable->setCurrentItem(currentItem);

    updateDisplayedLocation(lat, lon, alt);

    // Send the command.
    sendLocationToDevice(mLocationAgent, lat, lon, alt);

    // Go on to the next row
    mRowToSend++;
    if (mRowToSend >= mUi->loc_pathTable->rowCount()) {
        // No more to send. Same as clicking Stop.
        locationPlaybackStop();
    } else {
        // Set a timer for when this row should be sent
        theItem = mUi->loc_pathTable->item(mRowToSend, 0);
        double dTime = theItem->text().toDouble();
        int mSec = dTime * 1000.0;
        if (mSec < 0) mSec = 0;
        mTimer.setInterval(
                mSec / static_cast<double>(mUi->loc_playbackSpeed->currentIndex() + 1));
        mTimer.start();
    }
}

void LocationPage::geoDataThreadStarted() {
    mUi->loc_pathTable->setRowCount(0);
    SettingsTheme theme = getSelectedTheme();

    // Prevent the user from initiating a load gpx/kml while another load is already
    // in progress
    setButtonEnabled(mUi->loc_GpxKmlButton, theme, false);
    setButtonEnabled(mUi->loc_playStopButton, theme, false);
    mNowLoadingGeoData = true;
}

void LocationPage::finishGeoDataLoading(
        const QString& file_name,
        bool ok,
        const QString& error_message,
        bool ignore_error) {
    mGeoDataLoader = nullptr;
    if (ok) {
        QSettings settings;
        settings.setValue(Ui::Settings::LOCATION_PLAYBACK_FILE, file_name);
        populateTable(&mGpsFixesArray);
    } else if (!ignore_error) {
        showErrorDialog(error_message, tr("Geo Data Parser"));
    }
    SettingsTheme theme = getSelectedTheme();
    setButtonEnabled(mUi->loc_GpxKmlButton, theme, true);
    setButtonEnabled(mUi->loc_playStopButton, theme, true);
    mNowLoadingGeoData = false;
    emit(geoDataLoadingFinished());
}

void LocationPage::startupGeoDataThreadFinished(QString file_name, bool ok, QString error_message) {
    // on startup, we silently ignore the previously remebered geo data file being
    // missing or malformed.
    finishGeoDataLoading(file_name, ok, error_message, true);
}

void LocationPage::geoDataThreadFinished(QString file_name, bool ok, QString error_message) {
    finishGeoDataLoading(file_name, ok, error_message, false);
}

// Get the current location from the device. If that fails, use
// the saved location from this UI.
// (static function)
void LocationPage::getDeviceLocation(const QAndroidLocationAgent* locAgent,
                                     double* pLatitude,
                                     double* pLongitude,
                                     double* pAltitude)
{
    bool gotDeviceLoc = false;

    if (locAgent && locAgent->gpsGetLoc) {
        // Query the device
        gotDeviceLoc = locAgent->gpsGetLoc(pLatitude, pLongitude, pAltitude, nullptr);
    }

    if (!gotDeviceLoc) {
        // Use the saved settings
        QSettings settings;
        *pLatitude  = settings.value(Ui::Settings::LOCATION_RECENT_LATITUDE,
                                     kGplexLat).toDouble();
        *pLongitude = settings.value(Ui::Settings::LOCATION_RECENT_LONGITUDE,
                                     kGplexLon).toDouble();
        *pAltitude  = settings.value(Ui::Settings::LOCATION_RECENT_ALTITUDE,
                                     0.0).toDouble();
    }
}

// Send a GPS location to the device
// (static function)
void LocationPage::sendLocationToDevice(const QAndroidLocationAgent* locAgent,
                                        double latitude,
                                        double longitude,
                                        double altitude)
{
    QSettings settings;
    settings.setValue(Ui::Settings::LOCATION_RECENT_LATITUDE, latitude);
    settings.setValue(Ui::Settings::LOCATION_RECENT_LONGITUDE, longitude);
    settings.setValue(Ui::Settings::LOCATION_RECENT_ALTITUDE, altitude);

    if (locAgent && locAgent->gpsSendLoc) {
        // Send these to the device
        timeval timeVal = {};
        gettimeofday(&timeVal, nullptr);
        locAgent->gpsSendLoc(latitude, longitude, altitude, 4, &timeVal);
    }
}

void GeoDataLoaderThread::loadGeoDataFromFile(const QString& file_name, GpsFixArray* fixes) {
    mFileName = file_name;
    mFixes = fixes;
    start();
}

void GeoDataLoaderThread::run() {
    if (mFileName.isEmpty() || mFixes == nullptr) {
        emit(loadingFinished(mFileName, false, tr("No file to load")));
        return;
    }

    bool ok = false;
    std::string err_str;

    {
        QFileInfo file_info(mFileName);
        mFixes->clear();
        auto suffix = file_info.suffix().toLower();
        if (suffix == "gpx") {
            ok = GpxParser::parseFile(mFileName.toStdString().c_str(),
                                      mFixes, &err_str);
        } else if (suffix == "kml") {
            ok = KmlParser::parseFile(mFileName.toStdString().c_str(),
                                      mFixes, &err_str);
        } else {
            err_str = tr("Unknown file type").toStdString();
        }
    }

    auto err_qstring = QString::fromStdString(err_str);
    emit(loadingFinished(mFileName, ok, err_qstring));
}

GeoDataLoaderThread* GeoDataLoaderThread::newInstance(const QObject* handler,
                                                      const char* started_slot,
                                                      const char* finished_slot) {
    GeoDataLoaderThread* new_instance = new GeoDataLoaderThread();
    connect(new_instance, SIGNAL(started()), handler, started_slot);
    connect(new_instance, SIGNAL(loadingFinished(QString, bool, QString)), handler, finished_slot);

    // Make sure new_instance gets cleaned up after the thread exits.
    connect(new_instance, &QThread::finished, new_instance, &QObject::deleteLater);

    return new_instance;
}
