#include "geom.h"
#include "tool.h"

#include <maps/libs/cmdline/include/cmdline.h>
#include <maps/wikimap/mapspro/services/mrc/libs/config/include/config.h>
#include <maps/wikimap/mapspro/services/mrc/libs/db/include/feature_gateway.h>
#include <maps/wikimap/mapspro/services/mrc/libs/object/include/revision_loader.h>

#include <maps/wikimap/mapspro/libs/common/include/yandex/maps/wiki/common/extended_xml_doc.h>

#include <maps/libs/common/include/exception.h>
#include <maps/libs/log8/include/log8.h>

namespace mrc = maps::mrc;
namespace db = maps::mrc::db;

namespace {

db::TIds loadAllFeatureIdsByGeoms(
        maps::pgpool3::Pool& pool,
        maps::geolib3::MultiPolygon2 geom)
{
    auto txn = pool.slaveTransaction();

    INFO() << "Load all features from db by geometry";
    db::FeatureGateway gateway(*txn);

    auto ids = gateway.loadIds(
         db::table::Feature::pos.intersects(maps::geolib3::convertGeodeticToMercator(geom)),
         maps::sql_chemistry::orderBy(db::table::Feature::id).asc());

    INFO() << "Loaded ids count: " << ids.size();
    return ids;
}

} // namespace

int main(int argc, char* argv[]) try {
    maps::cmdline::Parser parser(
        "Tool for filling in privacy field in MRC photos");
    auto configPath = parser.string("config")
        .help("path to configuration");
    auto wikiConfigPath = parser.string("wiki-config")
        .required()
        .help("Path to services config for wikimap");
    auto secretVersion = parser.string("secret-version")
            .help("version for secrets from yav.yandex-team.ru");
    auto minFeatureId = parser.num("min-feature-id")
        .help("min feature id")
        .defaultValue(0);
    auto maxFeatureId = parser.num("max-feature-id")
        .help("max feature id")
        .defaultValue(0);
    auto batchSize = parser.num("batch-size")
        .help("batch size")
        .defaultValue(50000);
    auto isDryRun = parser.flag("dry-run")
        .help("don't modify db")
        .defaultValue(false);
    auto geoId = parser.num("geo-id")
        .help("geobase geoId. If set, min-feature-id and max-feature-id are ignored");
    auto optGeoIdPath = parser.string("geoid-path")
        .help("path to geoid coverage mms file");

    parser.parse(argc, argv);

    const auto config =
        maps::mrc::common::templateConfigFromCmdPath(secretVersion, configPath);

    std::string geoIdPath = config.externals().geoIdCoveragePath();
    if (optGeoIdPath.defined()) {
        geoIdPath = std::string(optGeoIdPath);
    }
    mrc::GeoIdProvider geoIdProvider(geoIdPath);

    auto poolHolder = config.makePoolHolder();

    maps::wiki::common::ExtendedXmlDoc wikiConfig(wikiConfigPath);
    maps::wiki::common::PoolHolder wiki(wikiConfig, "core", "tasks");
    auto objectLoader = mrc::object::makeRevisionLoader(wiki.pool().slaveTransaction());
    auto regionPrivacyPtr = mrc::privacy::makeCachingRegionPrivacy(*objectLoader, geoIdPath);

    if (geoId) {
        auto featureIds = loadAllFeatureIdsByGeoms(
            poolHolder.pool(), geoIdProvider.geomById(geoId));
        mrc::fillPrivacy(poolHolder.pool(), *regionPrivacyPtr,
                         featureIds, batchSize, isDryRun);
    } else {
        mrc::fillPrivacy(poolHolder.pool(), *regionPrivacyPtr,
                         minFeatureId, maxFeatureId, batchSize, isDryRun);
    }

    INFO() << "Done";
    return EXIT_SUCCESS;
}
catch (const maps::Exception& e) {
    ERROR() << e;
    return EXIT_FAILURE;
}
catch (const std::exception& e) {
    ERROR() << e.what();
    return EXIT_FAILURE;
}
