//
// Created by Dan Crosby on 3/17/20.
//

#include "TileModifier.hpp"

#include <algorithm>

namespace shardok {

auto MakeSingleModifier(const std::optional<double>& integ) -> SingleModifier {
    SingleModifier sm;
    if (integ.has_value()) { sm.mutable_integrity()->set_value(integ.value()); }

    return sm;
}

auto operator==(const SingleModifier& lhs, const SingleModifier& rhs) -> bool {
    if (lhs.has_integrity() != rhs.has_integrity()) return false;
    if (lhs.has_integrity() && lhs.integrity().value() != rhs.integrity().value()) return false;

    return true;
}

auto MakeTileModifier(const bool onFire) -> TileModifierProto {
    TileModifierProto tm;
    if (onFire) tm.mutable_fire();

    return tm;
}

auto AdjustedEffectiveIntegrity(const SingleModifier& mod, const double adjustment) -> double {
    const double oldEffective = mod.has_integrity() ? mod.integrity().value() : 0.0;
    return std::max(0.0, std::min(oldEffective + adjustment, 100.0));
}

void MutatingAdjustBridgeIntegrity(TileModifierProto* tm, const double adjustment) {
    double newEffectiveBridge = AdjustedEffectiveIntegrity(tm->bridge(), adjustment);
    if (newEffectiveBridge <= 0) {
        tm->clear_bridge();
    } else {
        *tm->mutable_bridge() = MakeSingleModifier(newEffectiveBridge);
    }
}

void MutatingAdjustCastleIntegrity(TileModifierProto* tm, const double adjustment) {
    if (tm->has_castle()) {
        const double newEffectiveCastle = AdjustedEffectiveIntegrity(tm->castle(), adjustment);
        tm->mutable_castle()->mutable_integrity()->set_value(newEffectiveCastle);
    }
}

void MutatingAdjustIceIntegrity(TileModifierProto* tm, const double adjustment) {
    double newEffectiveIce = AdjustedEffectiveIntegrity(tm->ice(), adjustment);
    if (newEffectiveIce <= 0) {
        tm->clear_ice();
    } else {
        *tm->mutable_ice() = MakeSingleModifier(newEffectiveIce);
    }
}

void MutatingAdjustSnowIntegrity(TileModifierProto* tm, const double adjustment) {
    double newEffectiveSnow = AdjustedEffectiveIntegrity(tm->snow(), adjustment);
    if (newEffectiveSnow <= 0) {
        tm->clear_snow();
    } else {
        *tm->mutable_snow() = MakeSingleModifier(newEffectiveSnow);
    }
}

}  // namespace shardok