/* This file is part of the KDE project
 * Copyright ( C ) 2007 Thorsten Zachmann <zachmann@kde.org>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Library General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or ( at your option ) any later version.
 *
 * This library 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
 * Library General Public License for more details.
 *
 * You should have received a copy of the GNU Library General Public License
 * along with this library; see the file COPYING.LIB.  If not, write to
 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

#include "TestPACopyPastePage.h"

#include "KoPAMasterPage.h"
#include "KoPAOdfPageSaveHelper.h"
#include "KoPAPage.h"
#include "KoPAPastePage.h"
#include <PAMock.h>

#include <QClipboard>
#include <QMimeData>

#include <KoDrag.h>
#include <KoOdf.h>
#include <KoPathShape.h>
#include <KoShapeLayer.h>

#include <QTest>

void TestPACopyPastePage::copyAndPaste(MockDocument *doc, QList<KoPAPageBase *> &pages, KoPAPageBase *after)
{
    paste(doc, copy(doc, pages), after);
}

QMimeData *TestPACopyPastePage::copy(MockDocument *doc, QList<KoPAPageBase *> &pages)
{
    KoPAOdfPageSaveHelper saveHelper(doc, pages);
    KoDrag drag;
    drag.setOdf(KoOdf::mimeType(doc->documentType()), saveHelper);
    return drag.mimeData();
}

void TestPACopyPastePage::paste(MockDocument *doc, QMimeData *data, KoPAPageBase *after)
{
    if (data->hasFormat(KoOdf::mimeType(doc->documentType()))) {
        KoPAPastePage paste(doc, after);
        paste.paste(doc->documentType(), data);
    }
    delete data;
}

void TestPACopyPastePage::addShape(KoPAPageBase *page)
{
    KoPathShape *path = new KoPathShape();
    path->lineTo(QPointF(10, 0));
    path->lineTo(QPointF(10, 10));
    path->setPosition(m_pos);
    m_pos += QPointF(1.0, 1.0);

    QList<KoShape *> shapes = page->shapes();
    if (!shapes.isEmpty()) {
        KoShapeLayer *layer = dynamic_cast<KoShapeLayer *>(shapes.last());
        layer->addShape(path);
    }
}

void TestPACopyPastePage::copyPasteSinglePage()
{
    MockDocument doc;

    KoPAMasterPage *master1 = new KoPAMasterPage();
    doc.insertPage(master1, 0);

    KoPAPage *page1 = new KoPAPage(master1);
    doc.insertPage(page1, 0);

    addShape(page1);

    QList<KoPAPageBase *> pages;
    pages.append(page1);
    copyAndPaste(&doc, pages, page1);

    QCOMPARE(doc.pages(true).size(), 1);
    QCOMPARE(doc.pages(false).size(), 2);
    QVERIFY(doc.pages(false).front() == page1);

    KoPAPageBase *page2 = doc.pages(false).last();
    QVERIFY(dynamic_cast<KoPAPage *>(page2)->masterPage() == master1);

    copyAndPaste(&doc, pages, page1);

    QCOMPARE(doc.pages(true).size(), 1);
    QCOMPARE(doc.pages(false).size(), 3);
    QVERIFY(doc.pages(false)[0] == page1);
    QVERIFY(doc.pages(false)[2] == page2);

    KoPAPageBase *page3 = doc.pages(false)[1];
    QVERIFY(dynamic_cast<KoPAPage *>(page3)->masterPage() == master1);

    QVERIFY(page1 != page2);
    QVERIFY(page1 != page3);
    QVERIFY(page2 != page3);

    copyAndPaste(&doc, pages, nullptr);

    QCOMPARE(doc.pages(true).size(), 1);
    QCOMPARE(doc.pages(false).size(), 4);
    QVERIFY(doc.pages(false)[1] == page1);
    QVERIFY(doc.pages(false)[2] == page3);
    QVERIFY(doc.pages(false)[3] == page2);

    QMimeData *data = copy(&doc, pages);
    addShape(master1);
    paste(&doc, data, page1);

    QCOMPARE(doc.pages(true).size(), 2);
    QVERIFY(doc.pages(true)[0] == master1);
    QCOMPARE(doc.pages(false).size(), 5);
    QVERIFY(doc.pages(false)[1] == page1);
    QVERIFY(doc.pages(false)[3] == page3);
    QVERIFY(doc.pages(false)[4] == page2);
}

void TestPACopyPastePage::copyPasteSingleMasterPage()
{
    MockDocument doc;

    KoPAMasterPage *master1 = new KoPAMasterPage();
    doc.insertPage(master1, 0);

    KoPAPage *page1 = new KoPAPage(master1);
    doc.insertPage(page1, 0);

    addShape(master1);

    QList<KoPAPageBase *> pages;
    pages.append(master1);
    copyAndPaste(&doc, pages, master1);

    QCOMPARE(doc.pages(false).size(), 1);
    QCOMPARE(doc.pages(true).size(), 2);
    QVERIFY(doc.pages(true).front() == master1);

    KoPAPageBase *master2 = doc.pages(true)[1];

    copyAndPaste(&doc, pages, master1);

    QCOMPARE(doc.pages(false).size(), 1);
    QCOMPARE(doc.pages(true).size(), 3);
    QVERIFY(doc.pages(true)[0] == master1);
    QVERIFY(doc.pages(true)[2] == master2);

    KoPAPageBase *master3 = doc.pages(true)[1];

    QVERIFY(master1 != master2);
    QVERIFY(master1 != master3);
    QVERIFY(master2 != master3);

    copyAndPaste(&doc, pages, nullptr);

    QCOMPARE(doc.pages(false).size(), 1);
    QCOMPARE(doc.pages(true).size(), 4);
    QVERIFY(doc.pages(true)[1] == master1);
    QVERIFY(doc.pages(true)[2] == master3);
    QVERIFY(doc.pages(true)[3] == master2);
}

void TestPACopyPastePage::copyPasteMultiplePages()
{
    MockDocument doc;

    KoPAMasterPage *master1 = new KoPAMasterPage();
    doc.insertPage(master1, 0);
    addShape(master1);

    KoPAMasterPage *master2 = new KoPAMasterPage();
    doc.insertPage(master2, master1);
    addShape(master2);

    KoPAPage *page1 = new KoPAPage(master1);
    doc.insertPage(page1, 0);

    KoPAPage *page2 = new KoPAPage(master2);
    doc.insertPage(page2, page1);

    KoPAPage *page3 = new KoPAPage(master1);
    doc.insertPage(page3, page2);

    QList<KoPAPageBase *> pages;
    pages.append(page1);
    pages.append(page2);
    copyAndPaste(&doc, pages, page2);

    QCOMPARE(doc.pages(true).size(), 2);
    QCOMPARE(doc.pages(false).size(), 5);
    QVERIFY(doc.pages(false)[0] == page1);
    QVERIFY(doc.pages(false)[1] == page2);
    QVERIFY(doc.pages(false)[4] == page3);

    KoPAPage *page4 = dynamic_cast<KoPAPage *>(doc.pages(false)[2]);
    KoPAPage *page5 = dynamic_cast<KoPAPage *>(doc.pages(false)[3]);

    QVERIFY(page4 != nullptr);
    QVERIFY(page4->masterPage() == master1);
    QVERIFY(page5 != nullptr);
    QVERIFY(page5->masterPage() == master2);

    QList<KoPAPageBase *> masterPages;
    masterPages.append(master1);
    copyAndPaste(&doc, masterPages, master2);

    QCOMPARE(doc.pages(true).size(), 3);
    QVERIFY(doc.pages(true)[0] == master1);
    QVERIFY(doc.pages(true)[1] == master2);

    KoPAMasterPage *master3 = dynamic_cast<KoPAMasterPage *>(doc.pages(true)[2]);
    QVERIFY(master3 != nullptr);

    KoPAPage *page6 = new KoPAPage(master3);
    doc.insertPage(page6, page3);

    pages.append(page6);
    QMimeData *data = copy(&doc, pages);
    addShape(master2);
    paste(&doc, data, page6);

    QCOMPARE(doc.pages(true).size(), 4);
    QCOMPARE(doc.pages(false).size(), 9);
    QVERIFY(doc.pages(false)[0] == page1);
    QVERIFY(doc.pages(false)[1] == page2);
    QVERIFY(doc.pages(false)[2] == page4);
    QVERIFY(doc.pages(false)[3] == page5);
    QVERIFY(doc.pages(false)[4] == page3);
    QVERIFY(doc.pages(false)[5] == page6);

    KoPAPage *page7 = dynamic_cast<KoPAPage *>(doc.pages(false)[6]);
    KoPAPage *page8 = dynamic_cast<KoPAPage *>(doc.pages(false)[7]);
    KoPAPage *page9 = dynamic_cast<KoPAPage *>(doc.pages(false)[8]);

    KoPAMasterPage *master4 = dynamic_cast<KoPAMasterPage *>(doc.pages(true)[3]);
    QVERIFY(master4 != nullptr);

    QVERIFY(page7 != nullptr);
    QVERIFY(page7->masterPage() == master1);
    QVERIFY(page8 != nullptr);
    QVERIFY(page8->masterPage() == master4);
    QVERIFY(page9 != nullptr);
    QVERIFY(page9->masterPage() == master1);
}

void TestPACopyPastePage::copyPasteMultipleMasterPages()
{
    MockDocument doc;

    KoPAMasterPage *master1 = new KoPAMasterPage();
    doc.insertPage(master1, 0);

    KoPAPage *page1 = new KoPAPage(master1);
    doc.insertPage(page1, 0);

    KoPAMasterPage *master2 = new KoPAMasterPage();
    doc.insertPage(master2, master1);

    QList<KoPAPageBase *> pages;
    pages.append(master1);
    pages.append(master2);
    copyAndPaste(&doc, pages, master2);

    QVERIFY(doc.pages(false).size() == 1);
    QVERIFY(doc.pages(true).size() == 4);
    QVERIFY(doc.pages(true)[0] == master1);
    QVERIFY(doc.pages(true)[1] == master2);

    KoPAMasterPage *master3 = dynamic_cast<KoPAMasterPage *>(doc.pages(true)[2]);
    QVERIFY(master3 != nullptr);
    KoPAMasterPage *master4 = dynamic_cast<KoPAMasterPage *>(doc.pages(true)[3]);
    QVERIFY(master4 != nullptr);
}

void TestPACopyPastePage::copyPasteMixedPages()
{
    MockDocument doc;

    KoPAMasterPage *master1 = new KoPAMasterPage();
    doc.insertPage(master1, 0);

    KoPAPage *page1 = new KoPAPage(master1);
    doc.insertPage(page1, 0);

    KoPAMasterPage *master2 = new KoPAMasterPage();
    doc.insertPage(master2, master1);

    QList<KoPAPageBase *> pages;
    pages.append(page1);
    pages.append(master2);
    QMimeData *data = copy(&doc, pages);
    addShape(master2);
    paste(&doc, data, page1);

    QVERIFY(doc.pages(false).size() == 2);
    QVERIFY(doc.pages(true).size() == 2);
    QVERIFY(doc.pages(true)[0] == master1);
    QVERIFY(doc.pages(true)[1] == master2);
}

QTEST_MAIN(TestPACopyPastePage)
