#include <QtGui>
#include <QLabel>
#include <QDebug>
#include <QDialog>
#include <QFileDialog>

#include "mainwindow.h"
#include "diagramitem.h"
#include "diagramscene.h"
#include "diagramtextitem.h"
#include "arrow.h"
#include "arrow2.h"
#include "itemmanager.h"

#include "framedialog.h"
#include <QPolygonF>

#include "ko.cpp"
#include "po.cpp"

//! [0]
MainWindow::MainWindow()
{
    qDebug("123456");
    //русский язык
    QTextCodec*codec=QTextCodec::codecForName("CP1251");
    QTextCodec::setCodecForCStrings(codec);
    createActions();
    createMenus();
    createToolBox();
    
    scene = new DiagramScene(itemMenu, this, sceneMenu);
    scene->setSceneRect(QRectF(0, 0, 1140, 810));


    connect(scene, SIGNAL(itemInserted(DiagramItem*)),
            this, SLOT(itemInserted(DiagramItem*)));
    connect(scene, SIGNAL(arrInserted(Arrow2 *, int, int, int, QPointF, int)),
            this, SLOT(arrInserted(Arrow2 *, int, int, int, QPointF, int)));
    connect(scene, SIGNAL(itemMoved()),
            this, SLOT(itemMoved()));
    connect(scene, SIGNAL(textInserted(DiagramTextItem*, QPointF)),
            this, SLOT(textInserted(DiagramTextItem*, QPointF)));
    connect(scene, SIGNAL(commentInserted(QGraphicsTextItem*, QPointF, int, int)),
            this, SLOT(commentInserted(QGraphicsTextItem*, QPointF, int, int)));
    connect(scene, SIGNAL(itemCommInserted(QString, int)),
            this, SLOT(itemCommInserted(QString, int)));
    connect(scene, SIGNAL(itemChangeKoords(DiagramItem*, QPointF)),
            this, SLOT(itemChangeKoords(DiagramItem*, QPointF)));
    connect(scene, SIGNAL(retItem(int)),
            this, SLOT(retItem(int)));
    manager = ItemManager(scene, itemMenu);
    statesManager = new States();
    createToolbars();


    view = new QGraphicsView(scene);
    // Не будем пока пользоваться лайаутом.
    setCentralWidget(view);
    setWindowTitle(tr("Diagramscene"));

    paintingFrame();
    statesManager->appendState(manager);

    //Добавляем фоновый рисунок сцены
    scene->setBackgroundBrush(QPixmap("images/background.png"));
    scene->update();
    // Создается ссылка на буфер обмена
    QClipboard *clipBoard=QApplication::clipboard();

    //ЗАГРУЗКА
    //открытие файла
    QFile file("settings.ini");

    file.open(QIODevice::ReadOnly);
    QDataStream rd(&file);


    //загружаем данные о блоках в массивы
    rd>>windowX; rd>>windowY; rd>>windowWidth; rd>>windowHeight; rd>>state;
    rd>>filename;

    qDebug() << QString::number(windowX) << QString::number(windowY) << QString::number(windowWidth) << QString::number(windowHeight) << QString::number(state);
    timer = new QTimer(this);
    connect(timer, SIGNAL(timeout()), this, SLOT(loadXY()));
    timer->start(10);

    file.close();
}

//! [0]

MainWindow::~MainWindow()
{
    QString filename;
    QFile file("Settings.ini");
    file.open(QIODevice::WriteOnly);
    QDataStream wr(&file);
    // wr.setVersion(QDataStream::Qt_4_7);
    //если рамку не редактировали, поля массивы надо заполнить пустыми строками
    wr << (int)geometry().x() << (int)geometry().y() << (int)geometry().width() << (int)geometry().height() << (int)windowState() << QString(manager.getFileName());
    file.close();
}

void MainWindow::closeEvent(QCloseEvent * event)
{
    filename = manager.getFileName();
    if (!manager.getISaved())
    {
        int btn = QMessageBox::question(0, "Warning!", "Do you want to save changes?", QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
        if (btn == QMessageBox::Yes)
        {
            if (filename == "")
            {
                class QString FileName = QFileDialog::getSaveFileName(0, "Select file to open...", "../saves/",  "(*.ide)");
                if (FileName.isEmpty())
                {
                    event->ignore();
                    return ;
                }
                else
                    filename = FileName;
            }
            manager.saving(filename);
            event->accept();
        }
        else
            if (btn == QMessageBox::Cancel)
            {
                event->ignore();
                return ;
            }
    }
}

void MainWindow::loadXY()
{
    if (state != 2)
    setGeometry(windowX, windowY, windowWidth, windowHeight);
    setWindowState(Qt::WindowStates(state));
    if (filename != "")
        manager.loading(filename);

    qDebug()<<filename;
    timer->stop();
}

void MainWindow::retItem(int ID)
{
    DiagramItem *item = manager.returnItem(ID);
    if(item->id() != -1)
        scene->setItem(item);
}


void MainWindow::buttonGroupClicked(int id)
{
    QList<QAbstractButton *> buttons = buttonGroup->buttons();
    foreach (QAbstractButton *button, buttons) {
        if (buttonGroup->button(id) != button)
            button->setChecked(false);
    }
    if (id == InsertTextButton) {
        scene->setMode(DiagramScene::InsertText);
    } else {
        scene->setItemType(DiagramItem::DiagramType(id));
        scene->setMode(DiagramScene::InsertItem);
    }
}

void MainWindow::deleteItem()
{
    foreach (QGraphicsItem *item, scene->selectedItems())
    {
        if (item->type() == Arrow2::Type)
        {
            qDebug("00");
            manager.arrowDeleted(qgraphicsitem_cast<Arrow2 *>(item));
            delete item;
            statesManager->appendState(manager);
        }
    }

    foreach (QGraphicsItem *item, scene->selectedItems())
    {
        if (item->type() == DiagramItem::Type)
        {
            qDebug("11");
            manager.itemDeleted(qgraphicsitem_cast<DiagramItem *>(item));
            delete item;
            statesManager->appendState(manager);
        }
    }

    foreach (QGraphicsItem *item, scene->selectedItems())
    {
        if (item->type() == DiagramTextItem::Type)
        {
            qDebug("22");
            manager.commentDeleted(qgraphicsitem_cast<DiagramTextItem *>(item));
            delete item;
            statesManager->appendState(manager);
        }
    }

        scene->fl = 0;
        scene->fl1 = 0;
}

void MainWindow::pointerGroupClicked(int)
{
    scene->setMode(DiagramScene::Mode(pointerTypeGroup->checkedId()));
}

void MainWindow::sceneScaleChanged(const QString &scale)
{
    double newScale = scale.left(scale.indexOf(tr("%"))).toDouble() / 100.0;
    QMatrix oldMatrix = view->matrix();
    view->resetMatrix();
    view->translate(oldMatrix.dx(), oldMatrix.dy());
    view->scale(newScale, newScale);
}




// Code by Kuts
//
void MainWindow::load()
{
    manager.load();
    statesManager->clear();
    int id = manager.returnID();
    scene->setID(id);
}
// Code by Kuts

void MainWindow::createToolBox()
{
    buttonGroup = new QButtonGroup(this);
    buttonGroup->setExclusive(false);
    connect(buttonGroup, SIGNAL(buttonClicked(int)),
            this, SLOT(buttonGroupClicked(int)));
    QHBoxLayout *layout = new QHBoxLayout;
    layout->addWidget(createCellWidget(tr("Process"),
                                       DiagramItem::Step));

    QToolButton *textButton = new QToolButton;
    textButton->setCheckable(true);
    textButton->setShortcut(tr("Ctrl+T"));
    textButton->setToolTip("New Text (Ctrl+T)");
    buttonGroup->addButton(textButton, InsertTextButton);
    textButton->setIcon(QIcon(QPixmap("images/textpointer.png")
                              .scaled(30, 30)));
    textButton->setIconSize(QSize(22, 22));
    textButton->setBaseSize(QSize(22, 22));
    QHBoxLayout *textLayout = new QHBoxLayout;
    textLayout->addWidget(textButton, 0, Qt::AlignHCenter);
    QWidget *textWidget = new QWidget;
    textWidget->setLayout(textLayout);
    layout->addWidget(textWidget);
    //! [21]
    QWidget *itemWidget = new QWidget;
    itemWidget->setLayout(layout);

    editToolBar2 = addToolBar(tr("Edit2"));
    editToolBar2->addWidget(itemWidget);
    editToolBar2->move(0,0);
    editToolBar2->setBaseSize(QSize(50, 26));
}
//! [22]

//! [23]
void MainWindow::createActions()
{
    deleteAction = new QAction(QIcon("images/delete.png"),
                               tr("&Delete"), this);
    deleteAction->setShortcut(tr("Delete"));
    deleteAction->setToolTip(tr("Delete item from diagram (Del)"));
    connect(deleteAction, SIGNAL(triggered()),
            this, SLOT(deleteItem()));

    //Undo
    undoAction = new QAction(QIcon("images/Undo.png"),
                             tr("&Undo"), this);
    undoAction->setShortcut(tr("Ctrl+Z"));
    undoAction->setToolTip(tr("Undo (Ctrl+Z)"));
    connect(undoAction, SIGNAL(triggered()),
            this, SLOT(undoState()));
    //Redo
    redoAction = new QAction(QIcon("images/Redo.png"),
                             tr("&Redo"), this);
    redoAction->setShortcut(tr("Ctrl+Y"));
    redoAction->setToolTip(tr("Redo (Ctrl+Y)"));
    connect(redoAction, SIGNAL(triggered()),
            this, SLOT(redoState()));



    arrowDownAction = new QAction(QIcon("images/linepointerD.png"),
                                  tr("&Arrow (Up)"), this);
    arrowDownAction->setShortcut(Qt::CTRL + Qt::Key_Up);
    arrowDownAction->setStatusTip(tr("ArrowD"));
    connect(arrowDownAction, SIGNAL(triggered()),
            this, SLOT(arrowDown()));


    arrowUpAction = new QAction(QIcon("images/linepointerU.png"),
                                tr("&Arrow (Down)"), this);
    arrowUpAction->setShortcut(Qt::CTRL + Qt::Key_Down);
    arrowUpAction->setStatusTip(tr("ArrowU"));
    connect(arrowUpAction, SIGNAL(triggered()),
            this, SLOT(arrowUp()));

    arrowRightAction = new QAction(QIcon("images/linepointer.png"),
                                   tr("&Arrow (Left)"), this);
    arrowRightAction->setShortcut(Qt::CTRL + Qt::Key_Left);
    arrowRightAction->setStatusTip(tr("ArrowR"));
    connect(arrowRightAction, SIGNAL(triggered()),
            this, SLOT(arrowBack()));

    arrowFrontAction = new QAction(QIcon("images/linepointer.png"),
                                   tr("&Arrow (Front)"), this);
    arrowFrontAction->setShortcut(Qt::CTRL + Qt::Key_Right);
    arrowFrontAction->setStatusTip(tr("ArrowF"));
    connect(arrowFrontAction, SIGNAL(triggered()),
            this, SLOT(arrowFront()));

    //Создание кнопочки для редактирования рамки
    frameAction = new QAction(QIcon("images/bold.png"),
                              tr("&Frame"), this);
    frameAction->setShortcut(tr("Ctrl+P"));
    frameAction->setToolTip(tr("Frame Edition (Ctrl+P)"));
    connect(frameAction, SIGNAL(triggered()),
            this, SLOT(setFrame()));


    nameAction = new QAction(QIcon("images/textpointer.png"),
                             tr("&Name"), this);
    nameAction->setShortcut(tr("Ctrl+Q"));
    nameAction->setStatusTip(tr("Name of block (Ctrl+Q)"));
    connect(nameAction, SIGNAL(triggered()),
            this, SLOT(nameItem()));

    weightAction = new QAction(QIcon("images/weightpointer.png"),
                               tr("&Weight"), this);
    weightAction->setShortcut(tr("Ctrl+W"));
    weightAction->setStatusTip(tr("Weight in man hours (Cltr+W)"));
    connect(weightAction, SIGNAL(triggered()),
            this, SLOT(weightItem()));

    //Poly
    qDebug()<<"creating newAction";
    newAction =new QAction("New Diagram", this);
    newAction->setShortcut(tr("Ctrl+N"));
    connect(newAction, SIGNAL(triggered()), this, SLOT(newDm()));

    qDebug()<<"creating saveAction";
    saveAction =new QAction("Save", this);
    saveAction->setShortcut(tr("Ctrl+S"));
    connect(saveAction, SIGNAL(triggered()), this, SLOT(save()));

    qDebug()<<"creating saveAsAction";
    saveAsAction =new QAction("SaveAs...", this);
    saveAsAction->setShortcut(tr("Ctrl+Shift+S"));
    connect(saveAsAction, SIGNAL(triggered()), this, SLOT(saveAs()));
    ////////////
    qDebug()<<"creating loadAction";
    loadAction = new QAction("Load", this);
    loadAction->setShortcut(tr("Ctrl+O"));
    connect(loadAction, SIGNAL(triggered()), this, SLOT(load()));
    //Poly
    qDebug()<<"creating exitAction";
    exitAction = new QAction(tr("E&xit"), this);
    exitAction->setShortcuts(QKeySequence::Quit);
    exitAction->setStatusTip(tr("Quit Scenediagram example"));
    connect(exitAction, SIGNAL(triggered()), this, SLOT(close()));

    //code by Deniska
    exportAction =new QAction("Export", this);
    exportAction->setShortcut(tr("Ctrl+E"));
    connect(exportAction, SIGNAL(triggered()), this, SLOT(expPicture()));
    // Действия для копирования, вставки элементов.
    copyAction = new QAction("Copy", this);
    copyAction->setShortcut(tr("Ctrl+C"));
    connect(copyAction, SIGNAL(triggered()), this, SLOT(copyItem()));
    pasteAction = new QAction("Paste", this);
    pasteAction->setShortcut(tr("Ctrl+V"));
    connect(pasteAction, SIGNAL(triggered()), this, SLOT(pasteItem()));

}

//! [24]
void MainWindow::createMenus()
{
    fileMenu = menuBar()->addMenu(tr("&File"));
    //////////////////
    fileMenu->addAction(newAction);
    fileMenu->addAction(loadAction);
    fileMenu->addAction(saveAction);
    fileMenu->addAction(saveAsAction);
    fileMenu->addSeparator();
    fileMenu->addAction(exportAction);
    fileMenu->addSeparator();
    //////////////////
    fileMenu->addAction(exitAction);

    fileMenu = menuBar()->addMenu(tr("&Edit"));
    fileMenu->addAction(copyAction);
    fileMenu->addAction(pasteAction);
    fileMenu->addSeparator();
    fileMenu->addAction(nameAction);
    fileMenu->addAction(weightAction);
    fileMenu->addAction(arrowDownAction);
    fileMenu->addAction(arrowUpAction);
    fileMenu->addAction(arrowRightAction);
    fileMenu->addAction(arrowFrontAction);
    fileMenu->addSeparator();
    fileMenu->addAction(undoAction);
    fileMenu->addAction(redoAction);

    //////////////////

    //itemMenu = menuBar()->addMenu(tr("&Item"));
    itemMenu = new QMenu;
    itemMenu->addAction(deleteAction);
    //itemMenu->addAction(undoAction);
    //itemMenu->addAction(redoAction);
    itemMenu->addAction(nameAction);
    itemMenu->addAction(weightAction);
    itemMenu->addAction(arrowDownAction);
    itemMenu->addAction(arrowUpAction);
    itemMenu->addAction(arrowRightAction);
    itemMenu->addAction(arrowFrontAction);
    itemMenu->addSeparator();

	sceneMenu = new QMenu;
    sceneMenu->addAction(undoAction);
    sceneMenu->addAction(redoAction);
}
//! [24]

//! [25]
void MainWindow::createToolbars()
{
    //! [25]
    editToolBar = addToolBar(tr("Edit"));
    editToolBar->addAction(deleteAction);
    editToolBar->addAction(undoAction);
    editToolBar->addAction(redoAction);


    QToolButton *pointerButton = new QToolButton;
    pointerButton->setCheckable(true);
    pointerButton->setChecked(true);
    pointerButton->setShortcut(tr("Ctrl+H"));
    pointerButton->setToolTip("Hand (Ctrl+H)");
    pointerButton->setIcon(QIcon("images/pointer.png"));
    QToolButton *linePointerButton = new QToolButton;
    linePointerButton->setCheckable(true);
    linePointerButton->setShortcut(tr("Ctrl+L"));
    linePointerButton->setToolTip("Line (Ctrl+L)");
    linePointerButton->setIcon(QIcon("images/linepointer.png"));
    QToolButton *stdrambut = new QToolButton;
    connect(stdrambut, SIGNAL(clicked()),
            this, SLOT(paintRam()));

    pointerTypeGroup = new QButtonGroup(this);
    pointerTypeGroup->addButton(pointerButton, int(DiagramScene::MoveItem));
    pointerTypeGroup->addButton(linePointerButton,
                                int(DiagramScene::InsertLine));
    connect(pointerTypeGroup, SIGNAL(buttonClicked(int)),
            this, SLOT(pointerGroupClicked(int)));

    sceneScaleCombo = new QComboBox;
    QStringList scales;
    scales << tr("50%") << tr("75%") << tr("100%") << tr("125%") << tr("150%");
    sceneScaleCombo->setToolTip("Scale");
    sceneScaleCombo->addItems(scales);
    sceneScaleCombo->setCurrentIndex(2);
    connect(sceneScaleCombo, SIGNAL(currentIndexChanged(QString)),
            this, SLOT(sceneScaleChanged(QString)));

    pointerToolbar = addToolBar(tr("Pointer type"));
    pointerToolbar->addWidget(pointerButton);
    pointerToolbar->addWidget(linePointerButton);
    pointerToolbar->addWidget(sceneScaleCombo);

    //Панелька с кнопочкой для изменения рамки
    frameToolBar = addToolBar(tr("FrameEdit"));
    frameToolBar->addAction(frameAction);

    //! [27]
}
//! [27]

//! [28]
QWidget *MainWindow::createBackgroundCellWidget(const QString &text,
                                                const QString &image)
{
    QToolButton *button = new QToolButton;
    button->setText(text);
    button->setIcon(QIcon(image));
    button->setIconSize(QSize(50, 50));
    button->setCheckable(true);
    backgroundButtonGroup->addButton(button);

    QGridLayout *layout = new QGridLayout;
    layout->addWidget(button, 0, 0, Qt::AlignHCenter);
    layout->addWidget(new QLabel(text), 1, 0, Qt::AlignCenter);

    QWidget *widget = new QWidget;
    widget->setLayout(layout);

    return widget;
}
//! [28]

//! [29]
QWidget *MainWindow::createCellWidget(const QString &text,
                                      DiagramItem::DiagramType type)
{

    DiagramItem item(type, itemMenu);
    //QIcon icon(item.image());
    QIcon icon("images/square.png");

    QToolButton *button = new QToolButton;
    button->setIcon(icon);
    button->setShortcut(tr("Ctrl+R"));
    button->setToolTip("New Block (Ctrl+R)");
    button->setIconSize(QSize(22, 22));
    button->setBaseSize(QSize(22, 22));
    button->setCheckable(true);
    buttonGroup->addButton(button, int(type));

    QGridLayout *layout = new QGridLayout;

    return button;
}

QMenu *MainWindow::createColorMenu(const char *slot, QColor defaultColor)
{
    QList<QColor> colors;
    colors << Qt::black << Qt::white << Qt::red << Qt::blue << Qt::yellow;
    QStringList names;
    names << tr("black") << tr("white") << tr("red") << tr("blue")
          << tr("yellow");

    QMenu *colorMenu = new QMenu(this);
    for (int i = 0; i < colors.count(); ++i) {
        QAction *action = new QAction(names.at(i), this);
        action->setData(colors.at(i));
        action->setIcon(createColorIcon(colors.at(i)));
        connect(action, SIGNAL(triggered()),
                this, slot);
        colorMenu->addAction(action);
        if (colors.at(i) == defaultColor) {
            colorMenu->setDefaultAction(action);
        }
    }
    return colorMenu;
}
//! [30]

//! [31]
QIcon MainWindow::createColorToolButtonIcon(const QString &imageFile,
                                            QColor color)
{
    QPixmap pixmap(50, 80);
    pixmap.fill(Qt::transparent);
    QPainter painter(&pixmap);
    QPixmap image(imageFile);
    QRect target(0, 0, 50, 60);
    QRect source(0, 0, 42, 42);
    painter.fillRect(QRect(0, 60, 50, 80), color);
    painter.drawPixmap(target, image, source);

    return QIcon(pixmap);
}
//! [31]

//! [32]
QIcon MainWindow::createColorIcon(QColor color)
{
    QPixmap pixmap(20, 20);
    QPainter painter(&pixmap);
    painter.setPen(Qt::NoPen);
    painter.fillRect(QRect(0, 0, 20, 20), color);

    return QIcon(pixmap);
}
//! [32]
//code by Kuts
void MainWindow::expPicture()
{
    QImage img(1080,768,QImage::Format_ARGB32_Premultiplied);
    QPainter p(&img);
    this->scene->render(&p);
    p.end();
	//Диалог для экспорта в файл
	QString FileName;
	FileName = QFileDialog::getSaveFileName(0, "Select file to exporting...", "../saves/",  "(*.png)");
    img.save(FileName);
}

void MainWindow::undoState()
{
    if(statesManager->countStates()>1 && !statesManager->isFirst())
    {
        manager=statesManager->undo();
        updateState();
    }
}
void MainWindow::redoState()
{
    if(statesManager->countStates()>1 && !statesManager->isLast())
    {
        manager=statesManager->redo();
        updateState();
    }
}

void MainWindow::updateState()
{

    scene->clear();
    manager.draw_items();
}
