// imapd/Session.hh
// This file is part of Decimail; see http://decimail.org
// (C) 2004 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 Imapd_Session_hh
#define Imapd_Session_hh

#include "Exception.hh"
#include "FileDescriptor.hh"

#include "DmDatabase.hh"

#include <string>
using namespace std;

namespace Imapd {

  class CommandParser;

  class CloseConnection: public Exception {
  public:
    void report(ostream& strm);
  };

  class Session {
  public:
    Session(FileDescriptor& i, FileDescriptor& o);
    ~Session();

    void run(void);

    FileDescriptor& get_in_fd(void) { return in_fd; }
    bool wait_for_imap_or_db(void);  // true = imap, false = db
    void send_any_unilateral_updates(bool block);

    void respond_ok(string tag, string msg);
    void respond_no(string tag, string msg);
    void respond_bad(string tag, string msg);
    void respond_untagged(string msg);
    void send_continuation_request(void);

    void flush(void);

    enum State { non_auth=1, auth=2, selected=4 };
    void set_state(State s) { state=s; }
    State get_state(void) const { return state; }
    void check_state(int allowed_states);

    DmDatabase& get_db(void) { return db; }

    void set_username(string u) { username=u; }
    void clear_username(void) { username=""; }
    string get_username(void) const { return username; }

    void set_mailbox(string m);
    void clear_mailbox(void) { mailbox=""; }
    string get_mailbox(void) const { return mailbox; }
    string get_mailbox_query(void) const { return mailbox_query; }

    vector<int> seqnum_to_msgid;
    map<int,int> msgid_to_seqnum;

    void get_msg_ids(void);

    void prefetch_messages(const list<int>& msg_ids);
    Message* get_message(int msg_id) { return cached_messages[msg_id]; }

    const int num;

  private:
    static int next_num;

    FileDescriptor& in_fd;
    FileDescriptor& out_fd;
    FileDescriptor::ostream out_strm;
    CommandParser* parser;  // only a pointer to avoid circular dependencies
    
    State state;

    DmDatabase db;

    string username;
    string mailbox;
    string mailbox_query;

    map<int,Message*> cached_messages;

    bool unreported_messages;

    void respond(string tag, string response, string msg);
  };



};

#endif
