#ifndef PKGUTIL_H
#define PKGUTIL_H

#include <string>
#include <set>
#include <map>
#include <iostream>

#define PKG_EXT         ".pkg.tar.gz"
#define PKG_DB          "var/lib/pkg/db"
#define PKG_REJECTED    "var/lib/pkg/rejected/"
#define VERSION_DELIM   '#'

#define EXIT_OK         0
#define EXIT_ERROR      1

using namespace std;

class pkgutil {
public:
   struct pkginfo_t {
      string version;
      set<string> files;
   };

   typedef map<string, pkginfo_t> packages_t;

   pkgutil();
   virtual ~pkgutil() {}
   virtual int run(int argc, char** argv) = 0;

protected:
   virtual const char* name() const = 0;

   // Database
   void db_open(const string& path);
   void db_commit();
   void db_add_pkg(const string& name, const pkginfo_t& info);
   bool db_find_pkg(const string& name);
   void db_rm_pkg(const string& name);
   void db_rm_pkg(const string& name, const set<string>& keep_list);
   void db_rm_files(set<string> files);
   set<string> db_find_conflicts(const string& name, const pkginfo_t& info);

   // Tar.gz
   pair<string, pkginfo_t> pkg_open(const string& filename) const;
   void pkg_install(const string& filename) const;

   // Common
   string trim_filename(const string& filename) const;
   bool file_exists(const string& filename) const;
   void print_version() const;
   void print_try_help() const;
   void print_invalid_option(const string& option) const;
   void print_option_missing() const;
   void check_argument(char** argv, int argc, int index) const;
   ostream& print_info() const { return cout << name() << ": "; }
   ostream& print_error() const { return cerr << name() << " error: "; }

   packages_t packages;
   string root;
};

#endif /* PKGUTIL_H */
