/* vim: set sw=4 sts=4 et foldmethod=syntax : */

/*
 * Copyright (c) 2007 Piotr Jaroszyński <peper@gentoo.org>
 *
 * This file is part of the Paludis package manager. Paludis is free software;
 * you can redistribute it and/or modify it under the terms of the GNU General
 * Public License version 2, as published by the Free Software Foundation.
 *
 * Paludis 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, write to the Free Software Foundation, Inc., 59 Temple
 * Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <paludis_python.hh>

#include <paludis/dep_spec.hh>
#include <paludis/query.hh>
#include <paludis/environment.hh>
#include <paludis/package_database_entry.hh>
#include <paludis/package_database.hh>
#include <paludis/util/collection.hh>

namespace p = paludis;
namespace pp = paludis::python;
namespace bp = boost::python;

void expose_package_database()
{
    static pp::register_exception<p::PackageDatabaseError>
        PackageDatabaseError("PackageDatabaseError");
    static pp::register_exception<p::PackageDatabaseLookupError>
        PackageDatabaseLookupError("PackageDatabaseLookupError");
    static pp::register_exception<p::AmbiguousPackageNameError>
        AmbiguousPackageNameError("AmbiguousPackageNameError");
    static pp::register_exception<p::DuplicateRepositoryError>
        DuplicateRepositoryError("DuplicateRepositoryError");
    static pp::register_exception<p::NoSuchPackageError>
        NoSuchPackageError("NoSuchPackageError");
    static pp::register_exception<p::NoSuchRepositoryError>
        NoSuchRepositoryError("NoSuchRepositoryError");

    bp::enum_<p::QueryOrder>
        qo("QueryOrder");
    qo.value("ORDER_BY_VERSION", p::qo_order_by_version);///< By version
    qo.value("GROUP_BY_SLOT", p::qo_group_by_slot);      ///< By version, with like slots adjacent
    qo.value("WHATEVER", p::qo_whatever);                ///< No particular order
    qo.value("LAST", p::last_qo);

    pp::register_shared_ptrs_to_python<p::PackageDatabase>();
    bp::class_<p::PackageDatabase, boost::noncopyable>
        pd("PackageDatabase",
                "A PackageDatabase can be queried for Package instances.\n",
                bp::no_init
          );
    std::tr1::shared_ptr<p::PackageDatabaseEntryCollection>
        (p::PackageDatabase::*query)(const p::Query &, const p::QueryOrder) const = &p::PackageDatabase::query;
    pd.def("query", query,
            "query(Query, QueryOrder) -> PackageDatabaseEntryCollection\n"
            "Query the repository."
          );
    pd.add_property("favourite_repository", &p::PackageDatabase::favourite_repository,
            "[ro] RepositoryName\n"
            "Name of our 'favourite' repository"
          );
    std::tr1::shared_ptr<const p::Repository>
        (p::PackageDatabase::* fetch_repository)(const p::RepositoryName &) const =
        &p::PackageDatabase::fetch_repository;
    pd.def("fetch_repository", fetch_repository,
            "fetch_repository(RepositoryName) -> Repository\n"
            "Fetch a named repository."
          );
    pd.def("fetch_unique_qualified_package_name", &p::PackageDatabase::fetch_unique_qualified_package_name,
            "fetch_unique_qualified_package_name(PackageNamePart) -> QualifiedPackageName\n"
            "Disambiguate a package name."
          );
    pd.def("more_important_than", &p::PackageDatabase::more_important_than,
            "more_important_than(RepositoryName, RepositoryName) -> bool\n"
            "Return true if the first repository is more important than the second."
          );
    pd.add_property("repositories",
            bp::range(&p::PackageDatabase::begin_repositories, &p::PackageDatabase::end_repositories),
            "[ro] Iterable of Repository\n"
            "Our repositories"
            );

    bp::register_ptr_to_python<std::tr1::shared_ptr<p::PackageDatabaseEntry> >();
    bp::class_<p::PackageDatabaseEntry>
        pde("PackageDatabaseEntry",
                "Holds an entry in a PackageDatabase, and used to identify"
                " a specific version of a package in a particular repository.",
                bp::init<const p::QualifiedPackageName &, const p::VersionSpec &, const p::RepositoryName &>(
                    "__init__(QualifiedPackageName, VersionSpec, RepositoryName)"
                    )
           );
    pde.def(bp::self_ns::str(bp::self));
    pde.def("__eq__", &p::PackageDatabaseEntry::operator==);
    pde.def("__ne__", &p::PackageDatabaseEntry::operator!=);

    pp::class_collection<p::PackageDatabaseEntryCollection>
        pdec("PackageDatabaseEntryCollection",
                "An iterable collection of PackageDatabaseEntry instances."
            );
}
