#ifndef QT_MAINWINDOW_HPP
#define QT_MAINWINDOW_HPP

#include <QMainWindow>
#include <QLabel>
#include <QEvent>
#include <QFocusEvent>
#include <QLabel>
#include <QShortcut>
#include <QIcon>

#include <memory>
#include <array>
#include <atomic>

#include "qt_vmmanager_protocol.hpp"

extern QTimer discordupdate;

class MediaMenu;
class RendererStack;

namespace Ui {
class MainWindow;
}

class MachineStatus;

class MainWindow : public QMainWindow {
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

    void         showMessage(int flags, const QString &header, const QString &message, bool richText);
    void         getTitle(wchar_t *title);
    void         blitToWidget(int x, int y, int w, int h, int monitor_index);
    QSize        getRenderWidgetSize();
    void         setSendKeyboardInput(bool enabled);
    void         reloadAllRenderers();
    QShortcut   *windowedShortcut;
    QKeySequence FindAcceleratorSeq(const char *name);

    std::array<std::unique_ptr<RendererStack>, 8> renderers;
signals:
    void paint(const QImage &image);
    void resizeContents(int w, int h);
    void resizeContentsMonitor(int w, int h, int monitor_index);
    void statusBarMessage(const QString &msg);
    void updateStatusBarPanes();
    void updateStatusBarActivity(int tag, bool active);
    void updateStatusBarEmpty(int tag, bool empty);
    void updateStatusBarTip(int tag);
    void updateMenuResizeOptions();
    void updateWindowRememberOption();
    void initRendererMonitor(int monitor_index);
    void destroyRendererMonitor(int monitor_index);
    void initRendererMonitorForNonQtThread(int monitor_index);
    void destroyRendererMonitorForNonQtThread(int monitor_index);
    void forceInterpretationCompleted();
    void hardResetCompleted();

    void setTitle(const QString &title);
    void setFullscreen(bool state);
    void setMouseCapture(bool state);

    void showMessageForNonQtThread(int flags, const QString &header, const QString &message, bool richText, std::atomic_bool *done);
    void getTitleForNonQtThread(wchar_t *title);

    void vmmRunningStateChanged(VMManagerProtocol::RunningState state);
    void vmmConfigurationChanged();
    void vmmGlobalConfigurationChanged();
public slots:
    void emitVmmSignal();
    void showSettings();
    void hardReset();
    void togglePause();
    void initRendererMonitorSlot(int monitor_index);
    void destroyRendererMonitorSlot(int monitor_index);
    void updateStatusEmptyIcons();
    void updateUiPauseState();
private slots:
    void on_actionForce_interpretation_triggered();
    void on_actionFullscreen_triggered();
    void on_actionSettings_triggered();
    void on_actionExit_triggered();
    void on_actionAuto_pause_triggered();
    void on_actionUpdate_mouse_every_CPU_frame_triggered();
    void on_actionPause_triggered();
    void on_actionCtrl_Alt_Del_triggered();
    void on_actionCtrl_Alt_Esc_triggered();
    void on_actionHard_Reset_triggered();
    void on_actionRight_CTRL_is_left_ALT_triggered();
    void on_actionKeyboard_requires_capture_triggered();
    void on_actionResizable_window_triggered(bool checked);
    void on_action0_5x_triggered();
    void on_action1x_triggered();
    void on_action1_5x_triggered();
    void on_action2x_triggered();
    void on_action3x_triggered();
    void on_action4x_triggered();
    void on_action5x_triggered();
    void on_action6x_triggered();
    void on_action7x_triggered();
    void on_action8x_triggered();
    void on_actionLinear_triggered();
    void on_actionNearest_triggered();
    void on_actionFullScreen_int_triggered();
    void on_actionFullScreen_int43_triggered();
    void on_actionFullScreen_keepRatio_triggered();
    void on_actionFullScreen_43_triggered();
    void on_actionFullScreen_stretch_triggered();
    void on_actionDocumentation_triggered();
    void on_actionAbout_86Box_triggered();
    void on_actionAbout_Qt_triggered();
    void on_actionForce_4_3_display_ratio_triggered();
    void on_actionRemember_size_and_position_triggered();
    void on_actionSpecify_dimensions_triggered();
    void on_actionHiDPI_scaling_triggered();
    void on_actionHide_status_bar_triggered();
    void on_actionHide_tool_bar_triggered();
    void on_actionUpdate_status_bar_icons_triggered();
    void on_actionTake_screenshot_triggered();
    void on_actionTake_raw_screenshot_triggered();
    void on_actionCopy_screenshot_triggered();
    void on_actionCopy_raw_screenshot_triggered();
    void toggleFullscreenUI();
    void on_actionMute_Unmute_triggered();
    void on_actionSound_gain_triggered();
    void on_actionPreferences_triggered();
    void on_actionEnable_Discord_integration_triggered(bool checked);
    void on_actionRenderer_options_triggered();
    void on_actionFast_forward_triggered();

    void refreshMediaMenu();
    void showMessage_(int flags, const QString &header, const QString &message, bool richText, std::atomic_bool *done = nullptr);
    void getTitle_(wchar_t *title);

    void on_actionMCA_devices_triggered();

protected:
    void keyPressEvent(QKeyEvent *event) override;
    void keyReleaseEvent(QKeyEvent *event) override;
    void focusInEvent(QFocusEvent *event) override;
    void focusOutEvent(QFocusEvent *event) override;
    bool eventFilter(QObject *receiver, QEvent *event) override;
    void showEvent(QShowEvent *event) override;
    void closeEvent(QCloseEvent *event) override;
    void changeEvent(QEvent *event) override;
    void resizeEvent(QResizeEvent *event) override;

private slots:
    void on_actionPen_triggered();

private slots:
    void on_actionCursor_Puck_triggered();

    void on_actionACPI_Shutdown_triggered();

private slots:
    void on_actionShow_non_primary_monitors_triggered();

    void on_actionOpen_screenshots_folder_triggered();

    void on_actionOpen_printer_tray_triggered();

    void on_actionApply_fullscreen_stretch_mode_when_maximized_triggered(bool checked);

private:
    Ui::MainWindow                *ui;
    std::unique_ptr<MachineStatus> status;
    std::shared_ptr<MediaMenu>     mm;

    void updateShortcuts();
    void processKeyboardInput(bool down, uint32_t keycode);
#ifdef Q_OS_MACOS
    uint32_t last_modifiers = 0;
    void     processMacKeyboardInput(bool down, const QKeyEvent *event);
#endif

    /* If main window should send keyboard input */
    bool send_keyboard_input = true;
    bool shownonce           = false;
    bool resizableonce       = false;
    bool vnc_enabled         = false;

    /* Full screen ON and OFF signals */
    bool fs_on_signal  = false;
    bool fs_off_signal = false;

    /* Reload the renderers after closing renderer options dialog. */
    bool reload_renderers = false;

    /* Mouse capture state before showing fullscreen UI */
    bool mouse_was_captured = false;

    friend class SpecifyDimensions;
    friend class Preferences;
    friend class PreferencesEmulator;
    friend class RendererCommon;
    friend class RendererStack;         // For UI variable access by non-primary renderer windows.
    friend class WindowsRawInputFilter; // Needed to reload renderers on style sheet changes.

    QLabel *caps_label, *scroll_label, *num_label, *kana_label;
    QIcon   caps_icon, scroll_icon, num_icon, kana_icon;
    QIcon   caps_icon_off, scroll_icon_off, num_icon_off, kana_icon_off;

    bool isShowMessage  = false;
    bool isNonPause     = false;
    bool window_blocked = false;
};

#endif // QT_MAINWINDOW_HPP
