
/*
 * (C) Copyright 2018- ECMWF.
 *
 * This software is licensed under the terms of the Apache Licence Version 2.0
 * which can be obtained at http://www.apache.org/licenses/LICENSE-2.0.
 * In applying this licence, ECMWF does not waive the privileges and immunities
 * granted to it by virtue of its status as an intergovernmental organisation nor
 * does it submit to any jurisdiction.
 */

/*
 * This software was developed as part of the EC H2020 funded project NextGenIO
 * (Project ID: 671951) www.nextgenio.eu
 */

#include "fdb5/api/local/PurgeVisitor.h"

#include "eckit/exception/Exceptions.h"

#include "fdb5/api/local/QueueStringLogTarget.h"
#include "fdb5/database/DB.h"
#include "fdb5/database/PurgeVisitor.h"
#include "fdb5/LibFdb5.h"

namespace fdb5 {
namespace api {
namespace local {

//----------------------------------------------------------------------------------------------------------------------


PurgeVisitor::PurgeVisitor(eckit::Queue<PurgeElement>& queue,
                           const metkit::mars::MarsRequest& request,
                           bool doit,
                           bool porcelain) :
    QueryVisitor<PurgeElement>(queue, request),
    out_(new QueueStringLogTarget(queue)),
    doit_(doit),
    porcelain_(porcelain) {}

/*
bool PurgeVisitor::visitCatalogue(const Catalogue& catalogue) {
    return false;
}*/

bool PurgeVisitor::visitDatabase(const Catalogue& catalogue, const Store& store) {

    // If the DB is locked for wiping, then it "doesn't exist"
    if (catalogue.wipeLocked()) return false;

    EntryVisitor::visitDatabase(catalogue, store);

    // If the request is overspecified relative to the DB key, then we
    // bail out here.

    if (!catalogue.key().match(request_)) {
        std::stringstream ss;
        ss << "Purging not supported for over-specified requests. "
           << "db=" << catalogue.key()
           << ", request=" << request_;
        throw eckit::UserError(ss.str(), Here());
    }

    ASSERT(!internalVisitor_);
    internalVisitor_.reset(catalogue.purgeVisitor(store));

    internalVisitor_->visitDatabase(catalogue, store);

    return true; // Explore contained indexes
}

bool PurgeVisitor::visitIndex(const Index& index) {
    internalVisitor_->visitIndex(index);

    return true; // Explore contained entries
}

void PurgeVisitor::visitDatum(const Field& field, const std::string& keyFingerprint) {
    internalVisitor_->visitDatum(field, keyFingerprint);
}

void PurgeVisitor::visitDatum(const Field&, const Key&) { NOTIMP; }

void PurgeVisitor::catalogueComplete(const Catalogue& catalogue) {
    internalVisitor_->catalogueComplete(catalogue);

    if (!porcelain_) {
        internalVisitor_->report(out_);
    }

    if (doit_ || porcelain_) {
        internalVisitor_->purge(out_, porcelain_, doit_);
    }

    // Cleanup

    internalVisitor_.reset();
}

//----------------------------------------------------------------------------------------------------------------------

} // namespace local
} // namespace api
} // namespace fdb5
