// common/DmDatabase.hh
// This file is part of Decimail; see http://decimail.org
// (C) 2004-2007 Philip Endecott
 
// 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
// 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, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
#ifndef DmDatabase_hh
#define DmDatabase_hh

#include "Database.hh"
#include "Message.hh"
#include "Exception.hh"

#include <string>
#include <list>


class DmDatabase: public pbe::Database {

public:

  typedef std::string username_t;
  typedef std::string mailbox_name_t;
  typedef std::string flag_t;
  typedef int         msg_id_t;
  typedef std::string passwd_t;
  typedef std::string rfc822_messageid_t;

  class MailboxDoesNotExist: public Exception {
  private:
    mailbox_name_t mailbox_name;
  public:
    MailboxDoesNotExist(std::string m): mailbox_name(m) {};
    void report (ostream& s) const;
  };

  class MailboxExists: public Exception {
  private:
    mailbox_name_t mailbox_name;
  public:
    MailboxExists(std::string m): mailbox_name(m) {};
    void report (ostream& s) const;
  };


  static void add_connection_string(std::string connection_string_);

  DmDatabase(void);

  std::string get_mailbox_query(username_t username, mailbox_name_t mailbox_name);

  auto_ptr<std::list<Message*> > get_messages(const std::list<msg_id_t>& msg_ids);

  class FlagExists: public Exception {
  private:
    flag_t flag;
  public:
    FlagExists(std::string f): flag(f) {}
    void report(ostream& s) const;
  };

  class FlagDoesNotExist: public Exception {
  private:
    flag_t flag;
  public:
    FlagDoesNotExist(std::string f): flag(f) {}
    void report(ostream& s) const;
  };

  void set_imap_mailbox_flag(username_t username, mailbox_name_t mailbox_name, flag_t flag);
  void clear_imap_mailbox_flag(username_t username, mailbox_name_t mailbox_name, flag_t flag);

  void set_imap_message_flag(username_t username, msg_id_t msg_id, flag_t flag);
  void clear_imap_message_flag(username_t username, msg_id_t msg_id, flag_t flag);
  void clear_all_imap_message_flags(username_t username, msg_id_t msg_id);
  std::list<std::string> get_imap_message_flags(username_t username, int msd_id);

  void insert(const Message& message, std::string owner);  // owner == username ?

  msg_id_t get_next_uid(void);

  void listen_for_new_messages(username_t username);
  bool check_for_new_messages(void);

  bool check_password(username_t username, passwd_t passwd);

  // Queries used by MessageDb:
  pbe::SingletonQuery<std::string, msg_id_t> q_get_headers;
  pbe::SingletonQuery<std::string, msg_id_t> q_get_body;
  pbe::Query<msg_id_t>                       q_get_headers_body;
  pbe::SingletonQuery<int, msg_id_t>         q_get_size;

  // Queries used by Configuration:
  pbe::Query<> q_get_configuration;

private:
  static std::string connection_string;

  void insert_addrs(msg_id_t msg_id, std::string what_addr,
		    const mimetic::AddressList addrs);

  void insert_realname(const mimetic::Mailbox& addr);

  // Queries used within DmDatabase:
  pbe::SingletonQuery<msg_id_t>                 q_get_next_msgid;
  pbe::OptQuery<std::string, username_t,mailbox_name_t> q_get_mailbox_query;
  pbe::Query<username_t,mailbox_name_t,flag_t>  q_insert_mailbox_flag;
  pbe::Query<username_t,mailbox_name_t,flag_t>  q_delete_mailbox_flag;
  pbe::Query<username_t,msg_id_t,flag_t>        q_insert_message_flag;
  pbe::Query<username_t,msg_id_t,flag_t>        q_delete_message_flag;
  pbe::Query<username_t,msg_id_t>               q_delete_message_flags;
  pbe::ColumnQuery<flag_t, username_t,msg_id_t> q_get_message_flags;
  pbe::SingletonQuery<int, username_t,passwd_t> q_check_password;
  pbe::Query<std::string,std::string>           q_insert_realname;
};



#endif
