/*
 * SPDX-FileCopyrightText: 2007 Jeremy Whiting <jpwhiting@kde.org>
 * SPDX-FileCopyrightText: 2007 Frederik Gladhorn <frederik.gladhorn@kdemail.net>
 * SPDX-License-Identifier: GPL-2.0-or-later
 */

#include "keduvocwordtype.h"

#include "keduvocexpression.h"

#include <QSet>

class KEduVocWordType::Private
{
public:
    // bitvector of word type flags
    KEduVocWordFlags m_flags;
    QList<KEduVocExpression *> m_expressions;
    // list of translations
    QList<KEduVocTranslation *> m_translations;
};

KEduVocWordType::KEduVocWordType(const QString &name, KEduVocWordType *parent)
    : KEduVocContainer(name, WordType, parent)
    , d(new Private)
{
}

KEduVocWordType::~KEduVocWordType()
{
    foreach (KEduVocTranslation *translation, d->m_translations) {
        translation->setWordType(nullptr);
    }
    delete d;
}

QList<KEduVocExpression *> KEduVocWordType::entries(EnumEntriesRecursive recursive)
{
    if (recursive == Recursive) {
        return entriesRecursive();
    }

    return d->m_expressions;
}

int KEduVocWordType::entryCount(EnumEntriesRecursive recursive)
{
    if (recursive == Recursive) {
        return entriesRecursive().count();
    }
    return d->m_expressions.count();
}

void KEduVocWordType::addTranslation(KEduVocTranslation *translation)
{
    // add to expression - if not already there because another translation of the same word is there.
    bool found = false;
    foreach (int i, translation->entry()->translationIndices()) {
        if (translation->entry()->translation(i)->wordType() == this) {
            found = true;
            break;
        }
    }
    if (!found) {
        d->m_expressions.append(translation->entry());
    }
    d->m_translations.append(translation);
    invalidateChildLessonEntries();
}

void KEduVocWordType::removeTranslation(KEduVocTranslation *translation)
{
    d->m_translations.removeAt(d->m_translations.indexOf(translation));

    // no lesson found - this entry is being deleted. remove all its siblings.
    if (!translation->entry()->lesson()) {
        const int index = d->m_expressions.indexOf(translation->entry());
        if (index != -1) {
            d->m_expressions.removeAt(index);
        }
    }

    // remove from cache if none of the translations use this word type (other than the one we are removing that should not be taken into account)
    bool found = false;
    foreach (int i, translation->entry()->translationIndices()) {
        if (translation->entry()->translation(i)->wordType() && translation->entry()->translation(i)->wordType() == this
            && translation->entry()->translation(i) != translation) {
            found = true;
            break;
        }
    }
    if (!found) {
        const int index = d->m_expressions.indexOf(translation->entry());
        if (index >= 0) {
            d->m_expressions.removeAt(index);
        }
    }

    invalidateChildLessonEntries();
}

KEduVocTranslation *KEduVocWordType::translation(int row)
{
    return d->m_translations.value(row);
}

KEduVocExpression *KEduVocWordType::entry(int row, EnumEntriesRecursive recursive)
{
    if (recursive == Recursive) {
        return entriesRecursive().value(row);
    }
    return entries().value(row);
}

KEduVocWordFlags KEduVocWordType::wordType() const
{
    return d->m_flags;
}

void KEduVocWordType::setWordType(KEduVocWordFlags flags)
{
    d->m_flags = flags;
}

KEduVocWordType *KEduVocWordType::childOfType(KEduVocWordFlags flags)
{
    if (d->m_flags == flags) {
        return this;
    }
    foreach (KEduVocContainer *child, childContainers()) {
        KEduVocWordType *result = static_cast<KEduVocWordType *>(child)->childOfType(flags);
        if (result) {
            return result;
        }
    }
    return nullptr;
}
