/*
    SPDX-FileCopyrightText: 2013-2016 Andreas Cord-Landwehr <cordlandwehr@kde.org>

    SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/

#include "learner.h"
#include "learner_p.h"
#include "liblearner_debug.h"
#include <QDir>
#include <QFileInfo>
#include <QPixmap>

using namespace LearnerProfile;

Learner::Learner(QObject *parent)
    : QObject(parent)
    , d(new LearnerPrivate)
{
    connect(this, &Learner::goalAdded, this, &Learner::goalCountChanged);
    connect(this, &Learner::goalRemoved, this, &Learner::goalCountChanged);
}

Learner::~Learner()
{
}

QString Learner::name() const
{
    return d->m_name;
}

void Learner::setName(const QString &name)
{
    if (name == d->m_name) {
        return;
    }
    d->m_name = name;
    Q_EMIT nameChanged();
}

int Learner::identifier() const
{
    return d->m_identifier;
}

void Learner::setIdentifier(int identifier)
{
    if (identifier == d->m_identifier) {
        return;
    }
    d->m_identifier = identifier;
    Q_EMIT identifierChanged();
}

QString Learner::imageUrl() const
{
    QString path = d->imagePath();
    if (!QFileInfo::exists(path)) {
        return QString();
    }
    return QStringLiteral("file://") + path;
}

void Learner::clearImage()
{
    const QString path{d->imagePath()};
    if (!QFileInfo::exists(path)) {
        return;
    }
    QFile file;
    if (!file.remove(path)) {
        qCCritical(LIBLEARNER_LOG) << "could not remove image:" << path;
    }
    Q_EMIT imageChanged();
}

void Learner::importImage(const QString &path)
{
    if (!QFileInfo::exists(path)) {
        qCWarning(LIBLEARNER_LOG) << "image path points to a non-existing file, aborting: " << path;
        return;
    }

    // create image directory if it does not exist
    QDir dir;
    if (!dir.exists(d->imageDirectory())) {
        dir.mkdir(d->imageDirectory());
    }

    QPixmap image = QPixmap(path);
    image = image.scaled(120, 120);
    if (!image.save(d->imagePath(), "PNG")) {
        qCCritical(LIBLEARNER_LOG()) << "could not save scaled image to" << d->imagePath();
    }
    Q_EMIT imageChanged();
    qCDebug(LIBLEARNER_LOG) << "saved scaled image from " << path << " at " << d->imagePath();
}

QList<LearningGoal *> Learner::goals() const
{
    return d->m_goals;
}

void Learner::addGoal(LearnerProfile::LearningGoal *goal)
{
    if (d->m_goals.contains(goal)) {
        return;
    }
    Q_EMIT goalAboutToBeAdded(goal, d->m_goals.count());
    d->m_goals.append(goal);
    Q_EMIT goalAdded();
}

void Learner::removeGoal(LearnerProfile::LearningGoal *goal)
{
    int index = d->m_goals.indexOf(goal);
    if (index < 0) {
        qCritical() << "Cannot remove goal, not found: aborting";
        return;
    }
    Q_EMIT goalAboutToBeRemoved(index);
    d->m_goals.removeAt(index);
    Q_EMIT goalRemoved(this, goal);
}

bool Learner::hasGoal(LearningGoal *goal) const
{
    for (LearningGoal *cmpGoal : std::as_const(d->m_goals)) {
        if (goal->identifier() == cmpGoal->identifier()) {
            return true;
        }
    }
    return false;
}

void Learner::setActiveGoal(LearningGoal *goal)
{
    if (d->m_activeGoal.contains(goal->category()) && d->m_activeGoal[goal->category()] == goal) {
        return;
    }

    d->m_activeGoal.insert(goal->category(), goal);
    Q_EMIT activeGoalChanged();
}

void Learner::setActiveGoal(Learner::Category categoryLearner, const QString &identifier)
{
    // TODO:Qt5 change method parameter to LearningGoal::Category
    // workaround for Q_INVOKABLE access of enum
    LearningGoal::Category category = static_cast<LearningGoal::Category>(categoryLearner);

    if (d->m_activeGoal.contains(category) && d->m_activeGoal[category]->identifier() == identifier) {
        return;
    }

    for (LearningGoal *goal : std::as_const(d->m_goals)) {
        if (goal->category() == category && goal->identifier() == identifier) {
            setActiveGoal(goal);
            return;
        }
    }
    qCritical() << "Could not select learning goal with ID " << identifier << ": not registered for this learner";
}

LearningGoal *Learner::activeGoal(Learner::Category categoryLearner) const
{
    // TODO:Qt5 change method parameter to LearningGoal::Category
    // workaround for Q_INVOKABLE access of enum
    LearningGoal::Category category = static_cast<LearningGoal::Category>(categoryLearner);
    if (!d->m_activeGoal.contains(category)) {
        qCWarning(LIBLEARNER_LOG) << "(Learner " << identifier() << ") No current learning goal set for category " << category
                                  << " : fall back to first in list";
        for (LearningGoal *goal : std::as_const(d->m_goals)) {
            if (goal->category() == category) {
                return goal;
            }
        }
        qCWarning(LIBLEARNER_LOG) << "No learning goals of category " << category << " registered";
        return nullptr;
    }
    return d->m_activeGoal[category];
}
