/*
 * read a KEduVocDocument from a KVTML file
 * SPDX-FileCopyrightText: 1999-2001 Ewald Arnold <kvoctrain@ewald-arnold.de>
 * SPDX-FileCopyrightText: 2005 Eric Pignet <eric at erixpage.com>
 * SPDX-FileCopyrightText: 2007 Peter Hedlund <peter.hedlund@kdemail.net>
 * SPDX-FileCopyrightText: 2007-2010 Frederik Gladhorn <gladhorn@kde.org>
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

#include "keduvockvtml2reader.h"

#include <KLocalizedString>
#include <QDir>
#include <QIODevice>
#include <QList>
#include <QTextStream>

#include "keduvoccommon_p.h"
#include "keduvockvtmlreader.h"
#include "keduvocleitnerbox.h"
#include "keduvoclesson.h"
#include "keduvocwordtype.h"
#include "kvtml2defs.h"

#include <QDebug>

KEduVocKvtml2Reader::KEduVocKvtml2Reader(QIODevice &file)
    : m_inputFile(&file)
{
}

bool KEduVocKvtml2Reader::isParsable()
{
    QTextStream ts(m_inputFile);
    QString line1(ts.readLine());
    QString line2(ts.readLine());

    m_inputFile->seek(0);
    return ((line1.startsWith(QLatin1String("<?xml"))) && (line2.indexOf(KVTML_TAG, 0) > 0));
}

KEduVocDocument::FileType KEduVocKvtml2Reader::fileTypeHandled()
{
    return KEduVocDocument::Kvtml;
}

KEduVocDocument::ErrorCode KEduVocKvtml2Reader::read(KEduVocDocument &doc)
{
    m_doc = &doc;

    QDomDocument domDoc(QStringLiteral("KEduVocDocument"));

    const QDomDocument::ParseResult parseResult = domDoc.setContent(m_inputFile);
    if (!parseResult) {
        qDebug() << "Unable to load document.Parse error in line " << parseResult.errorLine << ", col " << parseResult.errorColumn << ": "
                 << qPrintable(parseResult.errorMessage);
        return KEduVocDocument::InvalidXml;
    }

    QDomElement domElementKvtml = domDoc.documentElement();
    if (domElementKvtml.tagName() != KVTML_TAG) {
        m_errorMessage = i18n("This is not a KDE Vocabulary document.");
        return KEduVocDocument::FileTypeUnknown;
    }

    if (domElementKvtml.attribute(KVTML_VERSION).toFloat() < 2.0) {
        // read the file with the old format

        // first reset the file to the beginning
        m_inputFile->seek(0);
        KEduVocKvtmlReader oldFormat(*m_inputFile);

        // get the return value
        KEduVocDocument::ErrorCode retval = oldFormat.read(doc);

        // pass the errormessage up
        m_errorMessage = oldFormat.errorMessage();
        return retval;
    }

    //-------------------------------------------------------------------------
    // Information
    //-------------------------------------------------------------------------

    QDomElement info = domElementKvtml.firstChildElement(KVTML_INFORMATION);
    if (!info.isNull()) {
        if (!readInformation(info))
            return KEduVocDocument::FileReaderFailed;
    }

    bool result = readGroups(domElementKvtml); // read sub-groups

    return result ? KEduVocDocument::NoError : KEduVocDocument::FileReaderFailed;
}

bool KEduVocKvtml2Reader::readInformation(QDomElement &informationElement)
{
    // read the generator
    QDomElement currentElement = informationElement.firstChildElement(KVTML_GENERATOR);
    if (!currentElement.isNull()) {
        m_doc->setGenerator(currentElement.text());
        // add the version if it's there
        int pos = m_doc->generator().lastIndexOf(KVD_VERS_PREFIX);
        if (pos >= 0) {
            m_doc->setVersion(m_doc->generator().remove(0, pos + 2));
        }
    }

    // read the title
    currentElement = informationElement.firstChildElement(KVTML_TITLE);
    if (!currentElement.isNull()) {
        m_doc->setTitle(currentElement.text());
    }

    // read the author
    currentElement = informationElement.firstChildElement(KVTML_AUTHOR);
    if (!currentElement.isNull()) {
        m_doc->setAuthor(currentElement.text());
    }

    currentElement = informationElement.firstChildElement(KVTML_AUTHORCONTACT);
    if (!currentElement.isNull()) {
        m_doc->setAuthorContact(currentElement.text());
    }

    // read the license
    currentElement = informationElement.firstChildElement(KVTML_LICENSE);
    if (!currentElement.isNull()) {
        m_doc->setLicense(currentElement.text());
    }

    // read the comment
    currentElement = informationElement.firstChildElement(KVTML_COMMENT);
    if (!currentElement.isNull()) {
        m_doc->setDocumentComment(currentElement.text());
    }

    // read the category
    currentElement = informationElement.firstChildElement(KVTML_CATEGORY);
    if (!currentElement.isNull()) {
        m_doc->setCategory(currentElement.text());
    }

    return true;
}

bool KEduVocKvtml2Reader::readGroups(QDomElement &domElementParent)
{
    bool result = false;

    QDomElement groupElement = domElementParent.firstChildElement(KVTML_IDENTIFIERS);

    QDomElement currentElement;

    // ensure backwards compatibility - in kde 4.1 and earlier tenses were direct properties of the document class.
    // now they are moved into the individual identifiers
    QStringList tensesCompability;
    groupElement = groupElement.firstChildElement(KVTML_TENSES);
    if (!groupElement.isNull()) {
        tensesCompability = readTenses(groupElement);
    }

    groupElement = domElementParent.firstChildElement(KVTML_IDENTIFIERS);
    if (!groupElement.isNull()) {
        QDomNodeList entryList = groupElement.elementsByTagName(KVTML_IDENTIFIER);
        if (entryList.length() <= 0) {
            m_errorMessage = i18n("missing identifier elements from identifiers tag");
            return false;
        }

        for (int i = 0; i < entryList.count(); ++i) {
            currentElement = entryList.item(i).toElement();
            if (currentElement.parentNode() == groupElement) {
                result = readIdentifier(currentElement);
                if (!result) {
                    return false;
                }
                if (!tensesCompability.isEmpty()) {
                    m_doc->identifier(i).setTenseList(tensesCompability);
                }
            }
        }
    }

    groupElement = domElementParent.firstChildElement(KVTML_ENTRIES);
    if (!groupElement.isNull()) {
        QDomNodeList entryList = groupElement.elementsByTagName(KVTML_ENTRY);
        for (int i = 0; i < entryList.count(); ++i) {
            currentElement = entryList.item(i).toElement();
            if (currentElement.parentNode() == groupElement) {
                result = readEntry(currentElement);
                if (!result)
                    return false;
            }
        }
    }

    readSynonymsAntonymsFalseFriends(domElementParent);

    groupElement = domElementParent.firstChildElement(KVTML_WORDTYPES);
    if (!groupElement.isNull()) {
        readChildWordTypes(m_doc->wordTypeContainer(), groupElement);
    }

    groupElement = domElementParent.firstChildElement(KVTML_LEITNERBOXES);
    if (!groupElement.isNull()) {
        readLeitner(m_doc->leitnerContainer(), groupElement);
    }

    groupElement = domElementParent.firstChildElement(KVTML_LESSONS);
    if (!groupElement.isNull()) {
        readChildLessons(m_doc->lesson(), groupElement);
    }

    // Additional cleanup: Put orphaned entries without a lesson into a default lesson.
    KEduVocLesson *defaultLesson = new KEduVocLesson(i18n("Default Lesson"), m_doc->lesson());

    // now make sure we don't have any orphan entries
    foreach (KEduVocExpression *entry, m_allEntries) {
        if (!entry->lesson()) {
            defaultLesson->appendEntry(entry);
        }
    }

    if (defaultLesson->entryCount() > 0) {
        m_doc->lesson()->appendChildContainer(defaultLesson);
    } else {
        delete defaultLesson;
    }

    return true;
}

bool KEduVocKvtml2Reader::readIdentifier(QDomElement &identifierElement)
{
    bool result = true;
    int id = identifierElement.attribute(KVTML_ID).toInt(&result);
    if (!result) {
        m_errorMessage = i18n("identifier missing id");
        return false;
    }

    // generate empty identifiers in the doc
    for (int i = m_doc->identifierCount(); i <= id; i++) {
        m_doc->appendIdentifier(KEduVocIdentifier());
    }

    // the first element, create the identifier, even if empty
    QDomElement currentElement = identifierElement.firstChildElement(KVTML_NAME);
    m_doc->identifier(id).setName(currentElement.text());

    currentElement = identifierElement.firstChildElement(KVTML_LOCALE);
    m_doc->identifier(id).setLocale(currentElement.text());

    currentElement = identifierElement.firstChildElement(KVTML_IDENTIFIERTYPE);
    if (!currentElement.isNull()) {
        // TODO: do something with the type
    }

    // read sub-parts
    currentElement = identifierElement.firstChildElement(KVTML_ARTICLE);
    if (!currentElement.isNull()) {
        readArticle(currentElement, id);
    }

    currentElement = identifierElement.firstChildElement(KVTML_PERSONALPRONOUNS);
    if (!currentElement.isNull()) {
        KEduVocPersonalPronoun personalPronoun;
        readPersonalPronoun(currentElement, personalPronoun);
        m_doc->identifier(id).setPersonalPronouns(personalPronoun);
    }

    QStringList tenses = readTenses(identifierElement);

    m_doc->identifier(id).setTenseList(tenses);

    return result;
}

bool KEduVocKvtml2Reader::readEntry(QDomElement &entryElement)
{
    QDomElement currentElement;
    bool result = true;

    // get entry id
    int id = entryElement.attribute(KVTML_ID).toInt(&result);
    if (!result) {
        m_errorMessage = i18n("entry missing id");
        return false;
    }

    KEduVocExpression *expr = new KEduVocExpression;

    // read info tags: inactive, inquery, and sizehint
    currentElement = entryElement.firstChildElement(KVTML_DEACTIVATED);
    if (!currentElement.isNull()) {
        // set the active state of the expression
        if (currentElement.text() == KVTML_TRUE) {
            expr->setActive(false);
        } else {
            expr->setActive(true);
        }
    }

    // read translation children
    QDomNodeList translationList = entryElement.elementsByTagName(KVTML_TRANSLATION);

    for (int i = 0; i < translationList.count(); ++i) {
        currentElement = translationList.item(i).toElement();
        if (currentElement.parentNode() == entryElement) {
            result = readTranslation(currentElement, expr, i);
            if (!result)
                return false;
        }
    }

    if (expr->translationIndices().size() == 0) {
        qDebug() << "Found entry with no words in it." << id;
        expr->setTranslation(0, QString());
    }

    Q_ASSERT(expr);

    // TODO: probably should insert at id position with a check to see if it exists
    // may be useful for detecting corrupt documents
    m_allEntries[id] = expr;
    return result;
}

bool KEduVocKvtml2Reader::readTranslation(QDomElement &translationElement, KEduVocExpression *expr, int index)
{
    // read the text, grade, declension and conjugation
    expr->translation(index)->fromKVTML2(translationElement);
    QDomElement currentElement;

    // article grade
    currentElement = translationElement.firstChildElement(KVTML_ARTICLE);
    if (!currentElement.isNull()) {
        KEduVocText article;
        article.fromKVTML2(currentElement);
        expr->translation(index)->setArticle(article);
    }

    // comparisons
    currentElement = translationElement.firstChildElement(KVTML_COMPARISON);
    if (!currentElement.isNull()) {
        readComparison(currentElement, expr->translation(index));
    }

    // multiple choice
    currentElement = translationElement.firstChildElement(KVTML_MULTIPLECHOICE);
    if (!currentElement.isNull()) {
        readMultipleChoice(currentElement, expr->translation(index));
    }

    // image
    currentElement = translationElement.firstChildElement(KVTML_IMAGE);
    if (!currentElement.isNull()) {
        QUrl imageUrl(currentElement.text());
        if (imageUrl.isLocalFile() && QDir::isRelativePath(imageUrl.toLocalFile())) {
            imageUrl = QUrl(m_doc->url().toString(QUrl::RemoveFilename) + imageUrl.toLocalFile());
        }
        expr->translation(index)->setImageUrl(imageUrl);
    }

    // sound
    currentElement = translationElement.firstChildElement(KVTML_SOUND);
    if (!currentElement.isNull()) {
        QUrl soundUrl(currentElement.text());
        if (soundUrl.isLocalFile() && QDir::isRelativePath(soundUrl.toLocalFile())) {
            soundUrl = QUrl(m_doc->url().toString(QUrl::RemoveFilename) + soundUrl.toLocalFile());
        }
        expr->translation(index)->setSoundUrl(soundUrl);
    }

    return true;
}

bool KEduVocKvtml2Reader::readChildLessons(KEduVocLesson *parentLesson, QDomElement &lessonElement)
{
    QDomElement currentElement = lessonElement.firstChildElement(KVTML_CONTAINER);
    while (!currentElement.isNull()) {
        readLesson(parentLesson, currentElement);
        currentElement = currentElement.nextSiblingElement(KVTML_CONTAINER);
    }
    return true;
}

bool KEduVocKvtml2Reader::readLesson(KEduVocLesson *parentLesson, QDomElement &lessonElement)
{
    //<name>Lesson name</name>
    QDomElement currentElement = lessonElement.firstChildElement(KVTML_NAME);
    KEduVocLesson *lesson = new KEduVocLesson(currentElement.text(), parentLesson);
    parentLesson->appendChildContainer(lesson);

    readChildLessons(lesson, lessonElement);

    //<query>true</query>
    currentElement = lessonElement.firstChildElement(KVTML_INPRACTICE);
    lesson->setInPractice(currentElement.text() == KVTML_TRUE);

    //<entry id="123"/>
    currentElement = lessonElement.firstChildElement(KVTML_ENTRY);
    while (!currentElement.isNull()) {
        bool result = false;
        int entryId = currentElement.attribute(KVTML_ID).toInt(&result);
        if (result) {
            if (m_allEntries[entryId]) {
                lesson->appendEntry(m_allEntries[entryId]);
            }
        }
        currentElement = currentElement.nextSiblingElement(KVTML_ENTRY);
    }
    return true;
}

bool KEduVocKvtml2Reader::readSynonymsAntonymsFalseFriends(QDomElement &rootElement)
{
    QDomElement pairElement;
    for (int type = KEduVocTranslation::Synonym; type <= KEduVocTranslation::FalseFriend; type++) {
        switch (type) {
        case KEduVocTranslation::Synonym:
            pairElement = rootElement.firstChildElement(KVTML_SYNONYM);
            break;
        case KEduVocTranslation::Antonym:
            pairElement = rootElement.firstChildElement(KVTML_ANTONYM);
            break;
        case KEduVocTranslation::FalseFriend:
            pairElement = rootElement.firstChildElement(KVTML_FALSEFRIEND);
            break;
        }
        // pair
        pairElement = pairElement.firstChildElement(KVTML_PAIR);
        while (!pairElement.isNull()) {
            //<entry id="123"/>
            QDomElement entryElement = pairElement.firstChildElement(KVTML_ENTRY);
            int firstEntryId = entryElement.attribute(KVTML_ID).toInt();

            QDomElement translationElement = entryElement.firstChildElement(KVTML_TRANSLATION);
            int firstTranslationId = translationElement.attribute(KVTML_ID).toInt();

            // second entry
            entryElement = entryElement.nextSiblingElement(KVTML_ENTRY);
            int secondEntryId = entryElement.attribute(KVTML_ID).toInt();
            translationElement = entryElement.firstChildElement(KVTML_TRANSLATION);
            int secondTranslationId = translationElement.attribute(KVTML_ID).toInt();

            // pair them up
            KEduVocTranslation *first = m_allEntries[firstEntryId]->translation(firstTranslationId);
            KEduVocTranslation *second = m_allEntries[secondEntryId]->translation(secondTranslationId);

            switch (type) {
            case KEduVocTranslation::Synonym:
                first->addSynonym(second);
                second->addSynonym(first);
                break;
            case KEduVocTranslation::Antonym:
                first->addAntonym(second);
                second->addAntonym(first);
                break;
            case KEduVocTranslation::FalseFriend:
                first->addFalseFriend(second);
                second->addFalseFriend(first);
                break;
            }
            pairElement = pairElement.nextSiblingElement(KVTML_PAIR);
        }
    }
    return true;
}

bool KEduVocKvtml2Reader::readArticle(QDomElement &articleElement, int identifierNum)
/*
 <article>
  <singular>
    <definite>
        <male>der</male>
        <female>die</female>
        <neutral>das</neutral>
    </definite>
    <indefinite>
        <male>ein</male>
        <female>eine</female>
        <neutral>ein</neutral>
    </indefinite>
  </singular>
  <dual>
  </dual>
 </article>
*/
{
    QMap<int, KEduVocWordFlag::Flags> numbers;
    numbers[0] = KEduVocWordFlag::Singular;
    numbers[1] = KEduVocWordFlag::Dual;
    numbers[2] = KEduVocWordFlag::Plural;
    QMap<int, KEduVocWordFlag::Flags> genders;
    genders[0] = KEduVocWordFlag::Masculine;
    genders[1] = KEduVocWordFlag::Feminine;
    genders[2] = KEduVocWordFlag::Neuter;
    QMap<int, KEduVocWordFlag::Flags> defs;
    defs[0] = KEduVocWordFlag::Definite;
    defs[1] = KEduVocWordFlag::Indefinite;

    for (int num = 0; num <= 2; ++num) {
        QDomElement numberElement = articleElement.firstChildElement(KVTML_GRAMMATICAL_NUMBER[num]);
        if (!numberElement.isNull()) {
            // definite
            for (int def = 0; def <= 1; ++def) {
                QDomElement defElement = numberElement.firstChildElement(KVTML_GRAMMATICAL_DEFINITENESS[def]);
                if (!defElement.isNull()) {
                    // male
                    for (int gen = 0; gen <= 2; ++gen) {
                        QDomElement genderElement = defElement.firstChildElement(KVTML_GRAMMATICAL_GENDER[gen]);
                        if (!genderElement.isNull()) {
                            m_doc->identifier(identifierNum).article().setArticle(genderElement.text(), numbers[num] | defs[def] | genders[gen]);
                        }
                    }
                }
            }
        }
    }

    return true;
}

bool KEduVocKvtml2Reader::readChildWordTypes(KEduVocWordType *parentContainer, QDomElement &lessonElement)
{
    QDomElement currentElement = lessonElement.firstChildElement(KVTML_CONTAINER);
    while (!currentElement.isNull()) {
        readWordType(parentContainer, currentElement);
        currentElement = currentElement.nextSiblingElement(KVTML_CONTAINER);
    }
    return true;
}

bool KEduVocKvtml2Reader::readLeitner(KEduVocLeitnerBox *parentContainer, QDomElement &leitnerParentElement)
{
    QDomElement leitnerElement = leitnerParentElement.firstChildElement(KVTML_CONTAINER);
    while (!leitnerElement.isNull()) {
        QString name = leitnerElement.firstChildElement(KVTML_NAME).text();

        KEduVocLeitnerBox *leitner = new KEduVocLeitnerBox(name, parentContainer);
        parentContainer->appendChildContainer(leitner);
        // for leitner we only allow a flat list, no sub boxes.

        // read entries
        QDomElement entryElement = leitnerElement.firstChildElement(KVTML_ENTRY);
        while (!entryElement.isNull()) {
            // read <entry id="123"></entryid>
            int entryId = entryElement.attribute(KVTML_ID).toInt();
            QDomElement translationElement = entryElement.firstChildElement(KVTML_TRANSLATION);
            while (!translationElement.isNull()) {
                // <translation id="234"/>
                int translationId = translationElement.attribute(KVTML_ID).toInt();
                m_allEntries.value(entryId)->translation(translationId)->setLeitnerBox(leitner);
                translationElement = translationElement.nextSiblingElement(KVTML_TRANSLATION);
            }
            entryElement = entryElement.nextSiblingElement(KVTML_ENTRY);
        }
        leitnerElement = leitnerElement.nextSiblingElement(KVTML_CONTAINER);
    }
    return true;
}

bool KEduVocKvtml2Reader::readWordType(KEduVocWordType *parentContainer, QDomElement &typeElement)
{
    // set type and specialtype
    QString typeName = typeElement.firstChildElement(KVTML_NAME).text();

    KEduVocWordType *wordTypeContainer = new KEduVocWordType(typeName, parentContainer);
    parentContainer->appendChildContainer(wordTypeContainer);

    QString specialType = typeElement.firstChildElement(KVTML_SPECIALWORDTYPE).text();
    if (!specialType.isEmpty()) {
        // get the localized version
        if (specialType == KVTML_SPECIALWORDTYPE_NOUN) {
            wordTypeContainer->setWordType(KEduVocWordFlag::Noun);
        }
        if (specialType == KVTML_SPECIALWORDTYPE_VERB) {
            wordTypeContainer->setWordType(KEduVocWordFlag::Verb);
        }
        if (specialType == KVTML_SPECIALWORDTYPE_ADVERB) {
            wordTypeContainer->setWordType(KEduVocWordFlag::Adverb);
        }
        if (specialType == KVTML_SPECIALWORDTYPE_ADJECTIVE) {
            wordTypeContainer->setWordType(KEduVocWordFlag::Adjective);
        }
        if (specialType == KVTML_SPECIALWORDTYPE_NOUN_MALE) {
            wordTypeContainer->setWordType(KEduVocWordFlag::Noun | KEduVocWordFlag::Masculine);
        }
        if (specialType == KVTML_SPECIALWORDTYPE_NOUN_FEMALE) {
            wordTypeContainer->setWordType(KEduVocWordFlag::Noun | KEduVocWordFlag::Feminine);
        }
        if (specialType == KVTML_SPECIALWORDTYPE_NOUN_NEUTRAL) {
            wordTypeContainer->setWordType(KEduVocWordFlag::Noun | KEduVocWordFlag::Neuter);
        }
        if (specialType == KVTML_SPECIALWORDTYPE_CONJUNCTION) {
            wordTypeContainer->setWordType(KEduVocWordFlag::Conjunction);
        }
    } // special type

    // read entries
    QDomElement entryElement = typeElement.firstChildElement(KVTML_ENTRY);
    while (!entryElement.isNull()) {
        // read <entry id="123"></entryid>
        int entryId = entryElement.attribute(KVTML_ID).toInt();
        QDomElement translationElement = entryElement.firstChildElement(KVTML_TRANSLATION);
        while (!translationElement.isNull()) {
            // <translation id="234"/>
            int translationId = translationElement.attribute(KVTML_ID).toInt();
            m_allEntries.value(entryId)->translation(translationId)->setWordType(wordTypeContainer);
            translationElement = translationElement.nextSiblingElement(KVTML_TRANSLATION);
        }
        entryElement = entryElement.nextSiblingElement(KVTML_ENTRY);
    }

    readChildWordTypes(wordTypeContainer, typeElement);

    return true;
}

QStringList KEduVocKvtml2Reader::readTenses(QDomElement &tensesElement)
{
    QStringList tenses;

    QDomNodeList tenseNodes = tensesElement.elementsByTagName(KVTML_TENSE);
    for (int i = 0; i < tenseNodes.count(); ++i) {
        QDomElement currentElement = tenseNodes.item(i).toElement();
        if (currentElement.parentNode() == tensesElement) {
            tenses.append(currentElement.text());
        }
    }

    return tenses;
}

bool KEduVocKvtml2Reader::readComparison(QDomElement &domElementParent, KEduVocTranslation *translation)
/*
 <comparison>
   <comparative>better</comparative>
   <superlative>best</superlative>
 </comparison>
*/
{
    QDomElement currentElement;

    currentElement = domElementParent.firstChildElement(KVTML_COMPARATIVE);
    if (!currentElement.isNull()) {
        KEduVocText comparative;
        comparative.fromKVTML2(currentElement);

        // be compatible for KDE < 4.5
        if (comparative.text().isEmpty()) {
            comparative.setText(currentElement.text());
        }
        translation->setComparativeForm(comparative);
    }

    currentElement = domElementParent.firstChildElement(KVTML_SUPERLATIVE);
    if (!currentElement.isNull()) {
        KEduVocText superlative;
        superlative.fromKVTML2(currentElement);

        // be compatible for KDE < 4.5
        if (superlative.text().isEmpty()) {
            superlative.setText(currentElement.text());
        }
        translation->setSuperlativeForm(superlative);
    }
    return true;
}

bool KEduVocKvtml2Reader::readMultipleChoice(QDomElement &multipleChoiceElement, KEduVocTranslation *translation)
/*
 <multiplechoice>
   <choice>good</choice>
   <choice>better</choice>
   <choice>best</choice>
   <choice>best 2</choice>
   <choice>best 3</choice>
 </multiplechoice>
*/
{
    QDomElement currentElement;
    QDomNodeList choiceNodes = multipleChoiceElement.elementsByTagName(KVTML_CHOICE);
    for (int i = 0; i < choiceNodes.count(); ++i) {
        currentElement = choiceNodes.item(i).toElement();
        if (currentElement.parentNode() == multipleChoiceElement) {
            QStringList choices = translation->getMultipleChoice();
            choices.append(currentElement.text());
            translation->setMultipleChoice(choices);
        }
    }
    return true;
}

bool KEduVocKvtml2Reader::readPersonalPronoun(QDomElement &pronounElement, KEduVocPersonalPronoun &pronoun)
{
    pronoun.setMaleFemaleDifferent(!pronounElement.firstChildElement(KVTML_THIRD_PERSON_MALE_FEMALE_DIFFERENT).isNull());
    pronoun.setNeutralExists(!pronounElement.firstChildElement(KVTML_THIRD_PERSON_NEUTRAL_EXISTS).isNull());
    pronoun.setDualExists(!pronounElement.firstChildElement(KVTML_DUAL_EXISTS).isNull());

    QDomElement personElement = pronounElement.firstChildElement(KVTML_GRAMMATICAL_NUMBER[0]);
    if (!personElement.isNull()) {
        readPersonalPronounChild(personElement, pronoun, KEduVocWordFlag::Singular);
    }

    personElement = pronounElement.firstChildElement(KVTML_GRAMMATICAL_NUMBER[1]);
    if (!personElement.isNull()) {
        readPersonalPronounChild(personElement, pronoun, KEduVocWordFlag::Dual);
    }

    personElement = pronounElement.firstChildElement(KVTML_GRAMMATICAL_NUMBER[2]);
    if (!personElement.isNull()) {
        readPersonalPronounChild(personElement, pronoun, KEduVocWordFlag::Plural);
    }
    return true;
}

bool KEduVocKvtml2Reader::readPersonalPronounChild(QDomElement &personElement, KEduVocPersonalPronoun &pronoun, KEduVocWordFlags number)
{
    QMap<int, KEduVocWordFlag::Flags> persons;
    persons[0] = KEduVocWordFlag::First;
    persons[1] = KEduVocWordFlag::Second;
    persons[2] = (KEduVocWordFlag::Flags)((int)KEduVocWordFlag::Third | (int)KEduVocWordFlag::Masculine);
    persons[3] = (KEduVocWordFlag::Flags)((int)KEduVocWordFlag::Third | (int)KEduVocWordFlag::Feminine);
    persons[4] = (KEduVocWordFlag::Flags)((int)KEduVocWordFlag::Third | (int)KEduVocWordFlag::Neuter);

    for (int person = 0; person < 5; person++) {
        QDomElement currentElement = personElement.firstChildElement(KVTML_GRAMMATICAL_PERSON[person]);
        pronoun.setPersonalPronoun(currentElement.text(), persons[person] | number);
    }

    return true;
}

#include "moc_keduvockvtml2reader.cpp"
