// SPDX-License-Identifier: GPL-3.0-or-later

/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
*
* Copyright (C) 2013 - 2024, nymea GmbH
* Copyright (C) 2024 - 2025, chargebyte austria GmbH
*
* This file is part of nymea-energy-plugin-nymea.
*
* nymea-energy-plugin-nymea.s free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* nymea-energy-plugin-nymea.s 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with nymea-energy-plugin-nymea. If not, see <https://www.gnu.org/licenses/>.
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

#include "scoreentry.h"

ScoreEntry::ScoreEntry() : TimeFrame()
{

}

double ScoreEntry::value() const
{
    return m_value;
}

void ScoreEntry::setValue(double value)
{
    m_value = value;
}

float ScoreEntry::weighting() const
{
    return m_weighting;
}

void ScoreEntry::setWeighting(float weighting)
{
    m_weighting = weighting;
}

bool ScoreEntry::isNull() const
{
    return m_startDateTime.isNull() && m_endDateTime.isNull() && m_value == 0 && m_weighting == 0;
}

bool ScoreEntry::operator==(const ScoreEntry &other) const
{
    return m_startDateTime == other.startDateTime() &&
            m_endDateTime == other.endDateTime() &&
            m_value == other.value() &&
            m_weighting == other.weighting();
}

bool ScoreEntry::operator!=(const ScoreEntry &other) const
{
    return !operator==(other);
}

qhash_result_t qHash(const ScoreEntry &scoreEntry, qhash_result_t seed)
{
    QtPrivate::QHashCombine hash;
    seed = hash(seed, scoreEntry.startDateTime());
    seed = hash(seed, scoreEntry.endDateTime());
    seed = hash(seed, scoreEntry.value());
    seed = hash(seed, scoreEntry.weighting());
    return seed;
}


ScoreEntries::ScoreEntries(const QList<ScoreEntry> &other) :
    QList<ScoreEntry>(other)
{

}

QVariant ScoreEntries::get(int index) const
{
    return QVariant::fromValue(at(index));
}

void ScoreEntries::put(const QVariant &variant)
{
    append(variant.value<ScoreEntry>());
}

int ScoreEntries::availableFutureSchedules(const QDateTime &currentDateTime) const
{
    int availableScheduleCount = 0;
    foreach (const ScoreEntry &entry, *this) {
        if (entry.endDateTime() > currentDateTime)
            availableScheduleCount++;
    }

    return availableScheduleCount;
}

void ScoreEntries::sortByWeighting()
{
    std::sort(begin(), end(), [](const ScoreEntry &a, const ScoreEntry &b) -> bool {
        return a.weighting() > b.weighting();
    });
}

void ScoreEntries::sortByStartDateTime()
{
    std::sort(begin(), end(), [](const ScoreEntry &a, const ScoreEntry &b) -> bool {
        return a.startDateTime() < b.startDateTime();
    });
}

ScoreEntry ScoreEntries::getScoreEntry(const QDateTime &currentDateTime) const
{
    foreach (const ScoreEntry &entry, *this) {
        if (currentDateTime >= entry.startDateTime() && currentDateTime < entry.endDateTime())
            return entry;
    }

    return ScoreEntry();
}

bool ScoreEntries::availableUpTo(const QDateTime &dateTime) const
{
    foreach (const ScoreEntry &entry, *this) {
        // Note: do not use TimeFrame::isActive here, since we include the endDateTime for the evaluation
        if (dateTime >= entry.startDateTime() && dateTime <= entry.endDateTime())
            return true;
    }

    return false;
}

QDebug operator<<(QDebug debug, const ScoreEntry &dataEntry)
{
    const QDebugStateSaver saver(debug);
    debug.nospace() << "ScoreEntry(" << dataEntry.startDateTime().toString("dd.MM.yyyy hh:mm");
    debug.nospace() << " - " << dataEntry.endDateTime().toString("dd.MM.yyyy hh:mm");
    debug.nospace() << ", " << dataEntry.weighting() << " | " << dataEntry.value() << ")";
    return debug;
}

QDebug operator<<(QDebug debug, const ScoreEntries &scoreEntries)
{
    const QDebugStateSaver saver(debug);
    debug.nospace() << "ScoreEntries(" << scoreEntries.count() << ")\n";
    for (int i = 0; i < scoreEntries.count(); i++) {
        debug.nospace() << " - " << i << " -> " << scoreEntries.at(i) << "\n";
    }
    return debug;
}
