// Copyright (C) 2016 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0

#pragma once

#include "../core_global.h"

#include <utils/aspects.h>
#include <utils/id.h>

#include <functional>
#include <memory>

namespace Core {

namespace Internal {
class IOptionsPageWidgetPrivate;
class IOptionsPagePrivate;
class IOptionsPageProviderPrivate;
} // namespace Internal

class CORE_EXPORT IOptionsPageWidget : public QWidget
{
    Q_OBJECT

public:
    IOptionsPageWidget();
    ~IOptionsPageWidget();

    void setOnApply(const std::function<void()> &func);
    void setOnCancel(const std::function<void()> &func);
    void setDirtyChecker(const std::function<bool()> &func);

    virtual void apply();
    virtual void cancel();
    virtual bool isDirty() const;

private:
    friend class Internal::IOptionsPagePrivate;
    std::unique_ptr<Internal::IOptionsPageWidgetPrivate> d;
};

class CORE_EXPORT IOptionsPage
{
    Q_DISABLE_COPY_MOVE(IOptionsPage)

public:
    explicit IOptionsPage(bool registerGlobally = true);
    virtual ~IOptionsPage();

    static void registerCategory(
        Utils::Id id, const QString &displayName, const Utils::FilePath &iconPath);
    static const QList<IOptionsPage *> allOptionsPages();

    IOptionsPageWidget *createWidget();

    Utils::Id id() const;
    QString displayName() const;
    Utils::Id category() const;
    QString displayCategory() const;
    Utils::FilePath categoryIconPath() const;
    bool recreateOnCancel() const;

    std::optional<Utils::AspectContainer *> aspects() const;
    bool matches(const QRegularExpression &regexp) const;

protected:
    void setId(Utils::Id id);
    void setDisplayName(const QString &displayName);
    void setCategory(Utils::Id category);
    void setSettingsProvider(const std::function<Utils::AspectContainer *()> &provider);
    void setWidgetCreator(const std::function<IOptionsPageWidget *()> &widgetCreator);
    void setFixedKeywords(const QStringList &);
    void setRecreateOnCancel(bool on);
    void setAutoApply();

private:
    std::unique_ptr<Internal::IOptionsPagePrivate> d;
};

/*
    Alternative way for providing option pages instead of adding IOptionsPage
    objects into the plugin manager pool. Should only be used if creation of the
    actual option pages is not possible or too expensive at Qt Creator startup.
    (Like the designer integration, which needs to initialize designer plugins
    before the options pages get available.)
*/

class CORE_EXPORT IOptionsPageProvider
{
    Q_DISABLE_COPY_MOVE(IOptionsPageProvider)

public:
    IOptionsPageProvider();
    virtual ~IOptionsPageProvider();

    static const QList<IOptionsPageProvider *> allOptionsPagesProviders();

    Utils::Id category() const;
    QString displayCategory() const;
    Utils::FilePath categoryIconPath() const;

    virtual QList<IOptionsPage *> pages() const = 0;
    virtual bool matches(const QRegularExpression &regexp) const = 0;

protected:
    void setCategory(Utils::Id category);
    void setDisplayCategory(const QString &displayCategory);
    void setCategoryIconPath(const Utils::FilePath &iconPath);

    std::unique_ptr<Internal::IOptionsPageProviderPrivate> d;
};

// Which part of the settings page to pre-select, if applicable. In practice, this will
// usually be an item in some sort of (list) view.
void CORE_EXPORT setPreselectedOptionsPageItem(Utils::Id page, Utils::Id item);
Utils::Id CORE_EXPORT preselectedOptionsPageItem(Utils::Id page);

} // namespace Core
