/** @file
 * @brief List URLs of documents indexed by omindex
 */
/* Copyright 2014 Olly Betts
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see
 * <https://www.gnu.org/licenses/>.
 */

#include <config.h>

#include <xapian.h>

#include <cstdlib>
#include <string>
#include <iostream>

#include "gnu_getopt.h"
#include "hashterm.h"
#include "common/stringutils.h"

using namespace std;

#define PROG_NAME "omindex-list"
#define PROG_DESC "List URLs of documents indexed by omindex"

#define OPT_HELP 1
#define OPT_VERSION 2

static void show_usage() {
    cout << "Usage: " PROG_NAME " [OPTIONS] DATABASE...\n\n"
"Options:\n"
"  --help           display this help and exit\n"
"  --version        output version information and exit" << endl;
}

int
main(int argc, char **argv)
try {
    static const struct option long_opts[] = {
	{"help",	no_argument, 0, OPT_HELP},
	{"version",	no_argument, 0, OPT_VERSION},
	{NULL,		0, 0, 0}
    };

    int c;
    while ((c = gnu_getopt_long(argc, argv, "", long_opts, 0)) != -1) {
	switch (c) {
	    case OPT_HELP:
		cout << PROG_NAME " - " PROG_DESC "\n\n";
		show_usage();
		exit(0);
	    case OPT_VERSION:
		cout << PROG_NAME " - " PACKAGE_STRING << endl;
		exit(0);
	    default:
		show_usage();
		exit(1);
	}
    }

    if (argc - optind < 1) {
	show_usage();
	exit(1);
    }

    Xapian::Database db;
    while (argv[optind]) {
	db.add_database(Xapian::Database(argv[optind++]));
    }

    for (Xapian::TermIterator t = db.allterms_begin("U");
	 t != db.allterms_end("U");
	 ++t) {
	const string & term = *t;
	string url;
	if (term.size() < MAX_SAFE_TERM_LENGTH) {
	    url.assign(term, 1, string::npos);
	} else {
	    Xapian::PostingIterator p = db.postlist_begin(term);
	    if (p == db.postlist_end(term)) {
		cerr << "Unique term '" << term << "' has no postings!" << endl;
		continue;
	    }
	    Xapian::docid did = *p;
	    ++p;
	    if (p != db.postlist_end(term)) {
		cerr << "warning: Unique term '" << term << "' occurs "
		     << t.get_termfreq() << " times!" << endl;
	    }
	    const string & data = db.get_document(did).get_data();
	    size_t start;
	    if (startswith(data, "url=")) {
		start = CONST_STRLEN("url=");
	    } else {
		start = data.find("\nurl=");
		if (start == string::npos) {
		    cerr << "No 'url' field in document data for unique term '"
			 << term << "'" << endl;
		    continue;
		}
		start += CONST_STRLEN("\nurl=");
	    }
	    url.assign(data, start, data.find('\n', start) - start);
	}
	cout << url << endl;
    }
} catch (const Xapian::Error &error) {
    cerr << argv[0] << ": " << error.get_description() << endl;
    exit(1);
}
