#include <yandex/maps/wiki/diffalert/diff_context.h>
#include <maps/libs/common/include/exception.h>

#include <ostream>

namespace maps {
namespace wiki {
namespace diffalert {

OptionalObject::OptionalObject() : object_(nullptr) {}
OptionalObject::OptionalObject(Object* object) : object_(object) {}
OptionalObject::operator bool() const { return object_; }

Object* OptionalObject::checkAndGet() const { ASSERT(object_); return object_; }

Object& OptionalObject::operator*() { return *checkAndGet(); }
const Object& OptionalObject::operator*() const { return *checkAndGet(); }

Object* OptionalObject::operator->() { return checkAndGet(); }
const Object* OptionalObject::operator->() const { return checkAndGet(); }


bool DiffContext::stateChanged() const
{
    return !newObject() || !oldObject();
}

bool DiffContext::relationsChanged() const
{
    return !relationsAdded().empty() || !relationsDeleted().empty();
}

bool DiffContext::tableAttrsChanged() const
{
    return !tableAttrsAdded().empty() || !tableAttrsDeleted().empty();
}

bool DiffContext::changed() const
{
    return stateChanged()
        || categoryChanged()
        || attrsChanged()
        || tableAttrsChanged()
        || geomChanged()
        || relationsChanged();
}

std::ostream& operator<<(std::ostream& os, const ChangesPrinter& p)
{
    os << "(";
    if (p.diffContext.stateChanged()) {
        os << "state_";
    }
    if (p.diffContext.categoryChanged()) {
        os << "category_";
    }
    if (p.diffContext.attrsChanged()) {
        os << "attrs_";
    }
    if (p.diffContext.tableAttrsChanged()) {
        os << "tableAttrs_";
    }
    if (p.diffContext.geomChanged()) {
        os << "geom_";
    }
    if (p.diffContext.relationsChanged()) {
        os << "rels_";
    }
    os << ")";
    return os;
}

} // namespace diffalert
} // namespace wiki
} // namespace maps
