#include "mainwindow.h"

#include "graphicsItem/graphicsItemGroup.h"
#include "ui_mainwindow.h"

#include <QWidgetAction>
#include <QTableWidget>
#include <QSettings>
#include <QUndoStack>
#include <QGraphicsScene>
#include <QGraphicsItem>
#include <QFileDialog>
#include <QMessageBox>
#include <QFileInfo>

#include "DockAreaWidget.h"
#include "DockAreaTitleBar.h"
#include "DockAreaTabBar.h"
#include "FloatingDockContainer.h"
#include "DockComponentsFactory.h"

#include "QQuickDetailsViewMananger.h"
#include "propertyType/PropertyTypeCustomization_CustomType.h"
#include "propertyType/CustomType.h"
#include "QDetailsView.h"
#include "util/selectorManager.h"

#include "drawingPanel.h"
#include "designerScene.h"
#include "designerView.h"
#include "graphicElementsPanel.h"
#include "operationCommand.h"
#include "document.h"

using namespace ads;


CMainWindow::CMainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::CMainWindow)
{
    ui->setupUi(this);
    m_pUndoStack = nullptr;
    m_pDocument = nullptr;

    initializeDockUi();
    initializeAction();
    initializeDocument();

    connect(m_pGraphicElementsPanel,SIGNAL(addGraphicsItem(GraphicsItemType&)),m_pDrawingPanel,SLOT(onSignal_addGraphicsItem(GraphicsItemType&)));
}

CMainWindow::~CMainWindow()
{
    delete m_pDocument;
    delete ui;
}


void CMainWindow::closeEvent(QCloseEvent* event)
{
    // 检查是否有未保存的修改
    if (m_pDocument && m_pDocument->isModified()) {
        int ret = QMessageBox::warning(this, tr("确认关闭"),
            tr("文档已修改，是否保存？"),
            QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
        if (ret == QMessageBox::Save) {
            // 尝试保存，如果保存失败则取消关闭
            if (!m_pDocument->saveToFile()) {
                event->ignore();
                return;
            }
        } else if (ret == QMessageBox::Cancel) {
            event->ignore();
            return;
        }
    }

    // Delete dock manager here to delete all floating widgets. This ensures
    // that all top level windows of the dock manager are properly closed
    m_pDockManager->deleteLater();
	QMainWindow::closeEvent(event);
}

void CMainWindow::changeEvent(QEvent* event)
{
    if (event->type() == QEvent::WindowStateChange)
        m_pDrawingPanel->grahpicsViewZoomFit();
}

void CMainWindow::initializeDockUi()
{
    CDockManager::setConfigFlag(CDockManager::OpaqueSplitterResize, true);
    CDockManager::setConfigFlag(CDockManager::XmlCompressionEnabled, false);
    CDockManager::setConfigFlag(CDockManager::FocusHighlighting, true);
    m_pDockManager = new CDockManager(this);

    // Set central widget
    m_pDrawingPanel = new DrawingPanel();
    DesignerScene* designerScene = m_pDrawingPanel->getDesignerScene();
    connect(designerScene, SIGNAL(signalAddItem(GraphicsBaseItem*)), this, SLOT(onSignal_addItem(GraphicsBaseItem*)));
    connect(designerScene, SIGNAL(selectionChanged()), this, SLOT(onSignal_selectionChanged()));
    CDockWidget* centralDockWidget = new CDockWidget("CentralWidget");
    centralDockWidget->setWidget(m_pDrawingPanel);
    auto* centralDockArea = m_pDockManager->setCentralWidget(centralDockWidget);
    centralDockArea->setAllowedAreas(DockWidgetArea::OuterDockAreas);

    // create other dock widgets
    m_pGraphicElementsPanel = new GraphicElementsPanel();
    CDockWidget* grapicElementsDockWidget = new CDockWidget(QString::fromWCharArray(L"图元面板"));
    grapicElementsDockWidget->setWidget(m_pGraphicElementsPanel);
    grapicElementsDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget);
    grapicElementsDockWidget->resize(400, 150);
    grapicElementsDockWidget->setMinimumSize(200,150);
    m_pDockManager->addDockWidget(DockWidgetArea::LeftDockWidgetArea, grapicElementsDockWidget);
    ui->menuView->addAction(grapicElementsDockWidget->toggleViewAction());

	QQuickDetailsViewManager::Get()->registerPropertyTypeCustomization<QCustomType, PropertyTypeCustomization_CustomType>();

    m_pPropertiesEditorView = new QDetailsView();
    CDockWidget* propertiesDockWidget = new CDockWidget(QString::fromWCharArray(L"属性编辑器"));
    propertiesDockWidget->setWidget(m_pPropertiesEditorView);
    propertiesDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget);
    propertiesDockWidget->resize(550, 150);
    propertiesDockWidget->setMinimumSize(500,150);
    m_pPropertiesEditorView->setObject(m_pDrawingPanel->getQGraphicsScene());
    m_pDockManager->addDockWidget(DockWidgetArea::RightDockWidgetArea, propertiesDockWidget, centralDockArea);
    ui->menuView->addAction(propertiesDockWidget->toggleViewAction());
}

void CMainWindow::initializeAction()
{
    //撤销、重做
    m_pUndoStack = new QUndoStack(this);
    ui->actionUndo = m_pUndoStack->createUndoAction(this, tr("撤销"));
    ui->actionUndo->setIcon(QIcon::fromTheme(QString::fromUtf8("edit-undo")));
    ui->actionUndo->setShortcuts(QKeySequence::Undo);
    ui->actionRedo = m_pUndoStack->createRedoAction(this, tr("重做"));
    ui->actionRedo->setIcon(QIcon::fromTheme(QString::fromUtf8("edit-redo")));
    ui->actionRedo->setShortcuts(QKeySequence::Redo);
    ui->toolBar->addAction(ui->actionUndo);
    ui->toolBar->addAction(ui->actionRedo);
    ui->actionUndo->setEnabled(m_pUndoStack->canUndo());
    ui->actionRedo->setEnabled(m_pUndoStack->canRedo());

    ui->actionDelete->setShortcut(QKeySequence::Delete);

    connect(ui->actionDelete, SIGNAL(triggered()), this, SLOT(onSignal_deleteItem()));
    connect(ui->actionZoomIn, SIGNAL(triggered()), this, SLOT(onAction_zoomIn()));
    connect(ui->actionZoomOut, SIGNAL(triggered()), this, SLOT(onAction_zoomOut()));
    connect(ui->actionZoomFit, SIGNAL(triggered()), this, SLOT(onAction_zoomFit()));
    connect(ui->actionGroup, SIGNAL(triggered()), this, SLOT(onAction_createGroup()));
    connect(ui->actionUngroup, SIGNAL(triggered()), this, SLOT(onAction_destroyGroup()));

    // 文件操作
    connect(ui->actionNew, SIGNAL(triggered()), this, SLOT(onAction_new()));
    connect(ui->actionOpen, SIGNAL(triggered()), this, SLOT(onAction_open()));
    connect(ui->actionSave, SIGNAL(triggered()), this, SLOT(onAction_save()));
    connect(ui->actionSaveAs, SIGNAL(triggered()), this, SLOT(onAction_saveAs()));
}

void CMainWindow::onAction_zoomIn()
{
    m_pDrawingPanel->grahpicsViewZoomIn();
}

void CMainWindow::onAction_zoomOut()
{
    m_pDrawingPanel->grahpicsViewZoomOut();
}

void CMainWindow::onAction_zoomFit()
{
    m_pDrawingPanel->grahpicsViewZoomFit();
}

void CMainWindow::onAction_createGroup()
{
    GraphicsItemGroup* group = m_pDrawingPanel->createItemGroup();
    if(group)
    {
        QGraphicsScene* scene = m_pDrawingPanel->getQGraphicsScene();
        QUndoCommand* createItemGropu = new CreateItemGoupCommand(group, scene);
        m_pUndoStack->push(createItemGropu);
    }
}

void CMainWindow::onAction_destroyGroup()
{
    QGraphicsScene* scene = m_pDrawingPanel->getQGraphicsScene();
    QList<QGraphicsItem*> listItem = scene->selectedItems();
    if(listItem.count() != 1)
        return; //只能选择一个解组

    QGraphicsItem* item = listItem.first();
    if(!item)
        return;

    GraphicsItemGroup *group = dynamic_cast<GraphicsItemGroup*>(item);
    if(group)
    {
        QUndoCommand* destroyItemGropu = new DestroyItemGoupCommand(group, scene);
        m_pUndoStack->push(destroyItemGropu);
    }
}

void CMainWindow::onSignal_addItem(GraphicsBaseItem* item)
{
    if(item)
    {
        QUndoCommand* addItemCommand = new AddItemCommand(item, item->scene());
        m_pUndoStack->push(addItemCommand);
    }
}

void CMainWindow::onSignal_deleteItem()
{
    QGraphicsScene* scene = m_pDrawingPanel->getQGraphicsScene();
    if (scene && scene->selectedItems().isEmpty())
        return;

    QUndoCommand* deleteItemCommand = new DeleteItemCommand(scene);
    m_pUndoStack->push(deleteItemCommand); //push时会自动调用一次command的redo函数
}

void CMainWindow::onSignal_selectionChanged()
{
    QList<QGraphicsItem*> selectedItems = m_pDrawingPanel->getQGraphicsScene()->selectedItems();
    if(selectedItems.count() != 1) {
        m_pPropertiesEditorView->setObject(m_pDrawingPanel->getQGraphicsScene());
        return;
    }
    GraphicsBaseItem *item = static_cast<GraphicsBaseItem*>(selectedItems.first());
    m_pPropertiesEditorView->setObject(static_cast<QObject*>(item));
}

// =================================================================
// Document 初始化
// =================================================================

void CMainWindow::initializeDocument()
{
    // 创建新文档
    m_pDocument = new Document(this);

    // 关联 DesignerScene
    DesignerScene* scene = m_pDrawingPanel->getDesignerScene();
    m_pDocument->setScene(scene);

    // 连接 Document 信号
    connect(m_pDocument, &Document::modifiedChanged,
            this, &CMainWindow::onDocument_modifiedChanged);
    connect(m_pDocument, &Document::filenameChanged,
            this, &CMainWindow::onDocument_filenameChanged);
    connect(m_pDocument, &Document::saveStatusChanged,
            this, &CMainWindow::onDocument_saveStatusChanged);

    // 连接场景选择变化信号，当选择变化时标记文档为已修改
    // 注意：Qt6.5 之前没有 itemsAdded/itemsRemoved 信号
    connect(scene, &QGraphicsScene::selectionChanged,
            this, [this]() {
                if (m_pDocument && !m_pDocument->isModified()) {
                    m_pDocument->setModified(true);
                }
            });

    // 初始化窗口标题
    updateWindowTitle();

    // 将文件操作添加到文件菜单
    ui->menuFile->addAction(ui->actionNew);
    ui->menuFile->addAction(ui->actionOpen);
    ui->menuFile->addAction(ui->actionSave);
    ui->menuFile->addAction(ui->actionSaveAs);
    ui->menuFile->addSeparator();
}

// =================================================================
// Document 文件操作
// =================================================================

void CMainWindow::onAction_new()
{
    // 如果当前文档有修改，提示用户保存
    if (m_pDocument->isModified()) {
        int ret = QMessageBox::warning(this, tr("确认新建"),
            tr("当前文档已修改，是否保存？"),
            QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
        if (ret == QMessageBox::Save) {
            onAction_save();
        } else if (ret == QMessageBox::Cancel) {
            return;
        }
    }

    // 清空场景
    DesignerScene* scene = m_pDrawingPanel->getDesignerScene();
    scene->clear();

    // 创建新文档
    delete m_pDocument;
    m_pDocument = new Document(this);
    m_pDocument->setScene(scene);

    connect(m_pDocument, &Document::modifiedChanged,
            this, &CMainWindow::onDocument_modifiedChanged);
    connect(m_pDocument, &Document::filenameChanged,
            this, &CMainWindow::onDocument_filenameChanged);
    connect(m_pDocument, &Document::saveStatusChanged,
            this, &CMainWindow::onDocument_saveStatusChanged);

    updateWindowTitle();
}

void CMainWindow::onAction_open()
{
    // 如果当前文档有修改，提示用户保存
    if (m_pDocument->isModified()) {
        int ret = QMessageBox::warning(this, tr("确认打开"),
            tr("当前文档已修改，是否保存？"),
            QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel);
        if (ret == QMessageBox::Save) {
            onAction_save();
        } else if (ret == QMessageBox::Cancel) {
            return;
        }
    }

    QString fileName = QFileDialog::getOpenFileName(this, tr("打开文档"), "",
        tr("BayTemplate Files (*.bay);;All Files (*)"));
    if (fileName.isEmpty()) {
        return;
    }

    if (!m_pDocument->loadFromFile(fileName)) {
        QMessageBox::critical(this, tr("错误"), tr("无法打开文件：%1").arg(fileName));
    }
}

void CMainWindow::onAction_save()
{
    // 如果文档没有文件名，执行另存为
    if (m_pDocument->filename().isEmpty()) {
        onAction_saveAs();
        return;
    }

    if (m_pDocument->saveToFile()) {
        updateWindowTitle();
    }
}

void CMainWindow::onAction_saveAs()
{
    QString defaultFileName = m_pDocument->filename();
    if (defaultFileName.isEmpty()) {
        defaultFileName = QString("未命名.bay");
    }

    QString fileName = QFileDialog::getSaveFileName(this, tr("另存为"), defaultFileName,
        tr("BayTemplate Files (*.bay);;All Files (*)"));
    if (fileName.isEmpty()) {
        return;
    }

    // 确保文件扩展名为.bay
    if (!fileName.toLower().endsWith(".bay")) {
        fileName += ".bay";
    }

    if (!m_pDocument->saveAsToFile(fileName)) {
        QMessageBox::critical(this, tr("错误"), tr("无法保存文件：%1").arg(fileName));
    }
}

// =================================================================
// Document 信号处理
// =================================================================

void CMainWindow::onDocument_modifiedChanged(bool modified)
{
    updateWindowTitle();
}

void CMainWindow::onDocument_filenameChanged(const QString& filename)
{
    updateWindowTitle();
}

void CMainWindow::onDocument_saveStatusChanged(bool success, const QString& message)
{
    if (!success) {
        QMessageBox::warning(this, tr("文档操作"), message);
    }
}

void CMainWindow::updateWindowTitle()
{
    QString title = tr("BayTemplate");
    if (!m_pDocument->filename().isEmpty()) {
        title = QFileInfo(m_pDocument->filename()).fileName();
    } else {
        title = tr("未命名");
    }

    if (m_pDocument->isModified()) {
        title += " *";
    }

    setWindowTitle(title);
}
