#include "mainwindow.h"

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

#include <QWidgetAction>
#include <QTableWidget>
#include <QSettings>
#include <QUndoStack>
#include <QGraphicsScene>
#include <QGraphicsItem>

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

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

using namespace ads;


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

    initializeDockUi();
    initializeAction();

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

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


void CMainWindow::closeEvent(QCloseEvent* event)
{
    // Delete dock manager here to delete all floating widgets. This ensures
    // that all top level windows of the dock manager are properly closed
    DockManager->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);
    DockManager = new CDockManager(this);

    // Set central widget
    m_pDrawingPanel = new DrawingPanel();
    DesignerScene* designerScene = m_pDrawingPanel->getDesignerScene();
    connect(designerScene, SIGNAL(signalAddItem(QGraphicsItem*)), this, SLOT(onSignal_addItem(QGraphicsItem*)));
    CDockWidget* CentralDockWidget = new CDockWidget("CentralWidget");
    CentralDockWidget->setWidget(m_pDrawingPanel);
    auto* CentralDockArea = DockManager->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);
    DockManager->addDockWidget(DockWidgetArea::LeftDockWidgetArea, GrapicElementsDockWidget);
    ui->menuView->addAction(GrapicElementsDockWidget->toggleViewAction());

    QTableWidget* propertiesTable = new QTableWidget();
    propertiesTable->setColumnCount(3);
    propertiesTable->setRowCount(10);
    CDockWidget* PropertiesDockWidget = new CDockWidget(QString::fromWCharArray(L"属性编辑器"));
    PropertiesDockWidget->setWidget(propertiesTable);
    PropertiesDockWidget->setMinimumSizeHintMode(CDockWidget::MinimumSizeHintFromDockWidget);
    PropertiesDockWidget->resize(250, 150);
    PropertiesDockWidget->setMinimumSize(200,150);
    DockManager->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()));
}

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(QGraphicsItem* 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函数
}

