/*
 * This file is part of Maliit Plugins
 *
 * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). All rights reserved.
 *
 * Contact: Mohammad Anwari <Mohammad.Anwari@nokia.com>
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice, this list
 * of conditions and the following disclaimer.
 * Redistributions in binary form must reproduce the above copyright notice, this list
 * of conditions and the following disclaimer in the documentation and/or other materials
 * provided with the distribution.
 * Neither the name of Nokia Corporation nor the names of its contributors may be
 * used to endorse or promote products derived from this software without specific
 * prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
 * THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "utils.h"

#include "models/key.h"
#include "models/text.h"

#include "logic/eventhandler.h"

#include "view/setup.h"
#include "plugin/editor.h"
#include "inputmethodhostprobe.h"
#include "wordengineprobe.h"

#include <QtTest>
#include <QtCore>

using namespace MaliitKeyboard;

namespace Maliit {
bool operator==(const PreeditTextFormat &a, const PreeditTextFormat &b) {
    return ((a.start == b.start) and (a.length == b.length) and (a.preeditFace == b.preeditFace));
}
}

struct SetupTest
{
    SetupTest(bool enable_word_engine = true)
        : editor(EditorOptions(), new Model::Text, new Logic::WordEngineProbe, 0)
        , host()
        , event_handler()
    {
        editor.setHost(&host);
        editor.wordEngine()->setEnabled(enable_word_engine);
        Setup::connectEventHandlerToTextEditor(&event_handler, &editor);
    }

    Editor editor;
    InputMethodHostProbe host;
    Logic::EventHandler event_handler;
};

class TestPreeditString
    : public QObject
{
    Q_OBJECT

private:
    typedef QList<Maliit::PreeditTextFormat> FormatList;

    Q_SLOT void initTestCase()
    {
        qRegisterMetaType<FormatList>();
    }

    Q_SLOT void test_data()
    {
        QTest::addColumn<QStringList>("keys");
        QTest::addColumn<QString>("expected_last_preedit_string");
        QTest::addColumn<QString>("expected_commit_string");
        QTest::addColumn<FormatList>("expected_preedit_format");
        QTest::addColumn<bool>("word_engine_enabled");
        QTest::addColumn<int>("expected_cursor_position");

        QTest::newRow("No mouse events: expect empty commit string, should be no preedit face")
            << (QStringList())
            << "" << "" << FormatList() << true << 0;

        QTest::newRow("Only return pressed: expect empty commit string, should be no preedit face")
            << (QStringList() << "return")
            << "" << "" << FormatList() << true << 0;

        QTest::newRow("Release button over key 'a': expect commit string 'a', preedit face should be active.")
            << (QStringList() << "a" << "return")
            << "a" << "a" << (FormatList() << Maliit::PreeditTextFormat(0, 1, Maliit::PreeditActive)) << true << 0;

        QTest::newRow("Release button over key 'a', but no commit: expect empty commit string.")
            << (QStringList() << "a")
            << "a" << "" << (FormatList() << Maliit::PreeditTextFormat(0, 1, Maliit::PreeditActive)) << true << 1;

        QTest::newRow("Release button over keys 'c, b, d, a': expect commit string 'cbda', preedit face should be no candidates")
            << (QStringList() << "c" << "b" << "d" << "a" << "space")
            << "cbda" << "cbda " << (FormatList() << Maliit::PreeditTextFormat(0, 4, Maliit::PreeditNoCandidates)) << true << 0;

        QTest::newRow("Typing two words: expect commit string 'ab cd', with last preedit being 'cd', preedit face should be no candidates.")
            << (QStringList() << "a" << "b" << "space" << "c" << "d" << "return")
            << "cd" << "ab cd" << (FormatList() << Maliit::PreeditTextFormat(0, 2, Maliit::PreeditNoCandidates)) << true << 0;

        QTest::newRow("Typing one word 'abd': expect commit string 'abd', with last preedit being 'abd', preedit face should be default")
            << (QStringList() << "a" << "b" << "d" << "return")
            << "abd" << "abd" << (FormatList() << Maliit::PreeditTextFormat(0, 3, Maliit::PreeditDefault)) << true << 0;

        QTest::newRow("Typing one word 'abd' with word engine turned off: expect commit string 'abd', no preedit sent")
            << (QStringList() << "a" << "b" << "d")
            << "" << "abd" << FormatList() << false << 0;

        QTest::newRow("Typing one word 'ab' with word engine turned off: expect commit string 'ab', no preedit sent")
            << (QStringList() << "a" << "b")
            << "" << "ab" << FormatList() << false << 0;

        QTest::newRow("Typing one word 'bd' with word engine turned off: expect commit string 'bd', no preedit sent")
            << (QStringList() << "b" << "d")
            << "" << "bd" << FormatList() << false << 0;
    }

    Q_SLOT void test()
    {
        QFETCH(QStringList, keys);
        QFETCH(QString, expected_last_preedit_string);
        QFETCH(QString, expected_commit_string);
        QFETCH(QList<Maliit::PreeditTextFormat>, expected_preedit_format);
        QFETCH(bool, word_engine_enabled);
        QFETCH(int, expected_cursor_position);

        SetupTest test_setup(word_engine_enabled);

        Q_FOREACH (const QString &k, keys) {
            test_setup.event_handler.onKeyPressed(k, k);
            test_setup.event_handler.onKeyReleased(k, k);
        }

        TestUtils::waitForSignal(&test_setup.event_handler, SIGNAL(keyReleased(Key)));
        QCOMPARE(test_setup.host.lastPreeditString(), expected_last_preedit_string);
        QCOMPARE(test_setup.host.commitStringHistory(), expected_commit_string);
        QCOMPARE(test_setup.host.lastPreeditTextFormatList(), expected_preedit_format);
        QCOMPARE(test_setup.editor.text()->cursorPosition(), expected_cursor_position);
    }

};

QTEST_MAIN(TestPreeditString)
#include "ut_preedit-string.moc"
