/*
 * Copyright (C) by Klaas Freitag <freitag@owncloud.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * 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.
 */

#ifndef CONFIGFILE_H
#define CONFIGFILE_H

#include "qsferasynclib.h"

#include <QSettings>

#include <chrono>
#include <memory>
#include <optional>

class QWidget;
class QHeaderView;
class ExcludedFiles;

namespace OCC {

class AbstractCredentials;

/**
 * @brief The ConfigFile class
 * @ingroup libsync
 */
class QSFERA_SYNC_EXPORT ConfigFile
{
public:
    static QString configPath();
    static QString configFile();
    static QSettings makeQSettings();
    static std::unique_ptr<QSettings> makeQSettingsPointer();

    static bool exists();

    ConfigFile();

    enum Scope {
        UserScope,
        SystemScope
    };

    QString excludeFile(Scope scope) const;
    static QString defaultExcludeFile(); // doesn't access config dir

    /**
     * Creates a backup of the file
     *
     * Returns the path of the new backup.
     */
    QString backup() const;

    /* Server poll interval in milliseconds */
    std::chrono::milliseconds remotePollInterval(std::chrono::seconds defaultVal) const;
    /* Set poll interval. Value in milliseconds has to be larger than 5000 */
    void setRemotePollInterval(std::chrono::milliseconds interval);

    /**
     * Interval in milliseconds within which full local discovery is required
     *
     * Use -1 to disable regular full local discoveries.
     */
    std::chrono::milliseconds fullLocalDiscoveryInterval() const;

    bool crashReporter() const;
    void setCrashReporter(bool enabled);

    /** Whether to set up logging to a temp directory on startup.
     *
     * Configured via the log window. Not used if command line sets up logging.
     */
    bool automaticLogDir() const;
    void setAutomaticLogDir(bool enabled);

    /** Number of log files to keep */
    int automaticDeleteOldLogs() const;
    void setAutomaticDeleteOldLogs(int number);

    /** Whether to log http traffic */
    bool logHttp() const;

    /**
     * Set up HTTP logging.
     * This method should be called during application startup to make sure no messages are missed.
     */
    void configureHttpLogging(std::optional<bool> enable = std::nullopt);

    /** 0: no limit, 1: manual, >0: automatic */
    int useUploadLimit() const;
    int useDownloadLimit() const;
    void setUseUploadLimit(int);
    void setUseDownloadLimit(int);
    /** in kbyte/s */
    int uploadLimit() const;
    int downloadLimit() const;
    void setUploadLimit(int kbytes);
    void setDownloadLimit(int kbytes);

    bool pauseSyncWhenMetered() const;
    void setPauseSyncWhenMetered(bool isChecked);

    /** If we should move the files deleted on the server in the trash  */
    bool moveToTrash() const;
    void setMoveToTrash(bool);

    /// Used for testing, so we do not change the user's config file.
    static bool setConfDir(const QString &value);

    std::optional<QStringList> issuesWidgetFilter() const;
    void setIssuesWidgetFilter(const QStringList &checked);

    std::chrono::seconds timeout() const;

    void saveGeometry(QWidget *w);
    void restoreGeometry(QWidget *w);

    // how often the check about new versions runs
    std::chrono::milliseconds updateCheckInterval() const;

    bool skipUpdateCheck() const;
    void setSkipUpdateCheck(bool);

    QString updateChannel() const;
    void setUpdateChannel(const QString &channel);

    QString uiLanguage() const;
    void setUiLanguage(const QString &uiLanguage);

    void saveGeometryHeader(QHeaderView *header);
    bool restoreGeometryHeader(QHeaderView *header);

    /** The client version that last used this settings file.
        Updated by configVersionMigration() at client startup. */
    QString clientVersionWithBuildNumberString() const;
    void setClientVersionWithBuildNumberString(const QString &version);

    /// Add the system and user exclude file path to the ExcludedFiles instance.
    static void setupDefaultExcludeFilePaths(ExcludedFiles &excludedFiles);

private:
    QVariant getValue(const QString &param, const QVariant &defaultValue = QVariant()) const;
    void setValue(const QString &key, const QVariant &value);

    static QString _confDir;
};
}
#endif // CONFIGFILE_H
