// 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 "energytimeslot.h"

bool EnergyTimeSlot::isNull() const
{
    return !start.isValid() || !end.isValid();
}

bool EnergyTimeSlot::isActive(const QDateTime &dt) const
{
    return dt >= start && dt < end;
}

QVariantMap EnergyTimeSlot::toJson() const
{
    QVariantMap map;
    map.insert("start",               start.toUTC().toString(Qt::ISODateWithMs));
    map.insert("end",                 end.toUTC().toString(Qt::ISODateWithMs));
    map.insert("solarForecastW",      solarForecastW);
    map.insert("baseConsumptionW",    baseConsumptionW);
    map.insert("heatingNeedW",        heatingNeedW);
    map.insert("dhwNeedL",            dhwNeedL);
    map.insert("electricityPrice",    electricityPrice);
    map.insert("electricitySellPrice",electricitySellPrice);

    QVariantMap allocations;
    allocations.insert("ev",       allocatedToEV);
    allocations.insert("heatpump", allocatedToHP);
    allocations.insert("dhw",      allocatedToDHW);
    allocations.insert("battery",  allocatedToBattery);
    allocations.insert("feedin",   allocatedToFeedIn);
    map.insert("allocations", allocations);

    map.insert("netGridPowerW",       netGridPowerW);
    map.insert("estimatedCostEUR",    estimatedCostEUR);
    map.insert("selfSufficiencyPct",  selfSufficiencyPct);
    map.insert("decisionReason",      decisionReason);
    map.insert("decisionRules",       QVariant(decisionRules));
    map.insert("manualOverride",      manualOverride);
    if (!overrideReason.isEmpty())
        map.insert("overrideReason",  overrideReason);
    return map;
}

EnergyTimeSlot EnergyTimeSlot::fromJson(const QVariantMap &map)
{
    EnergyTimeSlot slot;
    slot.start               = QDateTime::fromString(map.value("start").toString(), Qt::ISODateWithMs).toUTC();
    slot.end                 = QDateTime::fromString(map.value("end").toString(), Qt::ISODateWithMs).toUTC();
    slot.solarForecastW      = map.value("solarForecastW").toDouble();
    slot.baseConsumptionW    = map.value("baseConsumptionW").toDouble();
    slot.heatingNeedW        = map.value("heatingNeedW").toDouble();
    slot.dhwNeedL            = map.value("dhwNeedL").toDouble();
    slot.electricityPrice    = map.value("electricityPrice").toDouble();
    slot.electricitySellPrice= map.value("electricitySellPrice").toDouble();

    QVariantMap alloc        = map.value("allocations").toMap();
    slot.allocatedToEV       = alloc.value("ev").toDouble();
    slot.allocatedToHP       = alloc.value("heatpump").toDouble();
    slot.allocatedToDHW      = alloc.value("dhw").toDouble();
    slot.allocatedToBattery  = alloc.value("battery").toDouble();
    slot.allocatedToFeedIn   = alloc.value("feedin").toDouble();

    slot.netGridPowerW       = map.value("netGridPowerW").toDouble();
    slot.estimatedCostEUR    = map.value("estimatedCostEUR").toDouble();
    slot.selfSufficiencyPct  = map.value("selfSufficiencyPct").toDouble();
    slot.decisionReason      = map.value("decisionReason").toString();
    slot.decisionRules       = map.value("decisionRules").toStringList();
    slot.manualOverride      = map.value("manualOverride").toBool();
    slot.overrideReason      = map.value("overrideReason").toString();
    return slot;
}

QDebug operator<<(QDebug debug, const EnergyTimeSlot &slot)
{
    const QDebugStateSaver saver(debug);
    debug.nospace() << "EnergyTimeSlot("
                    << slot.start.toString("dd.MM.yyyy hh:mm") << " - "
                    << slot.end.toString("hh:mm")
                    << ", solar=" << slot.solarForecastW << "W"
                    << ", price=" << slot.electricityPrice << "€"
                    << ", EV=" << slot.allocatedToEV << "W"
                    << ", reason=" << slot.decisionReason
                    << ")";
    return debug;
}
