#include "module.h"
#include <yandex/maps/wiki/validator/check.h>
#include <yandex/maps/wiki/validator/categories.h>

#include "../utils/misc.h"
#include "../utils/object_elements_within_aoi.h"
#include "../utils/relations_checks.h"
#include "../transport-thread-common/common.h"

#include <boost/none.hpp>

using maps::wiki::validator::categories::TRANSPORT_METRO_LINE;
using maps::wiki::validator::categories::TRANSPORT_METRO_STATION;
using maps::wiki::validator::categories::TRANSPORT_METRO_EXIT;
using maps::wiki::validator::categories::TRANSPORT_METRO_EL;

namespace maps {
namespace wiki {
namespace validator {
namespace checks {

VALIDATOR_SIMPLE_CHECK( transport_metro_relations,
        TRANSPORT_METRO_LINE, TRANSPORT_METRO_STATION,
        TRANSPORT_METRO_EXIT, TRANSPORT_METRO_EL )
{
    utils::runTransportElementsRelationsCheck<TRANSPORT_METRO_EL, TRANSPORT_METRO_LINE>(
            context, Severity::Error);

    utils::runFeatureRelationsCheck<TRANSPORT_METRO_LINE>(context);

    context->objects<TRANSPORT_METRO_LINE>().visit(
        [&](const TransportLine* metroLine) {
            if (!utils::objectElementsWithinAoi<TRANSPORT_METRO_LINE>(context, metroLine)) {
                return;
            }

            if (metroLine->stations().empty()) {
                context->critical(
                    "metro-line-without-stations",
                    boost::none,
                    { metroLine->id() });
            }
        }
    );

    context->objects<TRANSPORT_METRO_STATION>().visit(
        [&](const TransportMetroStation* metroStation){
            if (metroStation->stops().empty()) {
                context->error(
                        "station-not-assigned-to-thread",
                        metroStation->geom(),
                        { metroStation->id()});
            }
        }
    );

    context->objects<TRANSPORT_METRO_EXIT>().visit(
        [&](const TransportMetroExit* metroExit) {
            if (metroExit->station() == 0) {
                context->critical(
                    "stray-metro-exit",
                    metroExit->geom(),
                    { metroExit->id() });
            }
        }
    );
}

VALIDATOR_SIMPLE_CHECK(transport_metro_operator_relations,  TRANSPORT_METRO_LINE)
{
    performOperatorBindingCheck<TRANSPORT_METRO_LINE>(context);
}

} // namespace checks
} // namespace validator
} // namespace wiki
} // namespace maps
