/*
 * Fooyin
 * Copyright © 2023, Luke Taylor <luket@pm.me>
 *
 * Fooyin 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 3 of the License, or
 * (at your option) any later version.
 *
 * Fooyin 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with Fooyin.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#pragma once

#include "fygui_export.h"

#include <core/track.h>

#include <QPointer>
#include <QWidget>

#include <set>

class QWidget;

namespace Fooyin {
class ActionManager;
class SettingsManager;
class FYGUI_EXPORT PropertiesDialogSession
{
public:
    void reset(const TrackList& tracks);

    [[nodiscard]] const TrackList& originalTracks() const;
    [[nodiscard]] const TrackList& workingTracks() const;
    [[nodiscard]] TrackList activeTracks() const;

    [[nodiscard]] const std::set<int>& activeTrackIndexes() const;
    [[nodiscard]] bool isAllTracksScope() const;
    bool setActiveTrackIndexes(std::set<int> trackIndexes);

    void updateTracks(const TrackList& tracks);
    void acceptChanges();

    [[nodiscard]] bool hasChanges() const;
    [[nodiscard]] bool hasOnlyStatChanges() const;
    [[nodiscard]] int trackRevision(int index) const;

private:
    TrackList m_originalTracks;
    TrackList m_workingTracks;
    std::set<int> m_activeTrackIndexes;
    std::vector<int> m_pendingRevisions;
    qsizetype m_pendingCount{0};
};

class FYGUI_EXPORT PropertiesTabWidget : public QWidget
{
    Q_OBJECT

public:
    explicit PropertiesTabWidget(QWidget* parent)
        : QWidget{parent}
    { }

    [[nodiscard]] virtual bool canApply() const;

    virtual void load();
    virtual void apply();
    virtual void finish();

    virtual void setSession(PropertiesDialogSession* session);
    virtual void setTrackScope(const TrackList& tracks);
    virtual void updateTracks(const TrackList& tracks);

    [[nodiscard]] virtual bool isAvailableForScope(const TrackList& tracks) const;
    [[nodiscard]] virtual bool hasPendingScopeChanges() const;
    [[nodiscard]] virtual bool commitPendingChanges();

Q_SIGNALS:
    void pendingChangesStateChanged();
    void tracksChanged(const Fooyin::TrackList& tracks);
};

using WidgetBuilder = std::function<PropertiesTabWidget*(const TrackList& tracks)>;

class PropertiesTab
{
public:
    PropertiesTab(QString title, WidgetBuilder widgetBuilder, int index = -1);
    virtual ~PropertiesTab() = default;

    [[nodiscard]] int index() const;
    [[nodiscard]] QString title() const;
    [[nodiscard]] PropertiesTabWidget* widget(const TrackList& tracks) const;
    [[nodiscard]] bool hasVisited() const;

    void load(const TrackList& tracks);
    void updateIndex(int index);
    void setVisited(bool visited);

    virtual void apply();
    virtual void finish();

private:
    int m_index;
    QString m_title;
    WidgetBuilder m_widgetBuilder;
    mutable QPointer<PropertiesTabWidget> m_widget;
    bool m_loaded;
    bool m_visited;
};

class FYGUI_EXPORT PropertiesDialog : public QObject
{
    Q_OBJECT

public:
    using TabList = std::vector<PropertiesTab>;

    explicit PropertiesDialog(ActionManager* actionManager, SettingsManager* settings, QObject* parent = nullptr);
    ~PropertiesDialog() override;

    void addTab(const QString& title, const WidgetBuilder& widgetBuilder);
    void addTab(const PropertiesTab& tab);
    void insertTab(int index, const QString& title, const WidgetBuilder& widgetBuilder);

    void show(const TrackList& tracks);

private:
    ActionManager* m_actionManager;
    SettingsManager* m_settings;
    QAction* m_toggleScopeAction;
    QAction* m_previousTrackAction;
    QAction* m_nextTrackAction;
    TabList m_tabs;
};
} // namespace Fooyin
