/*
 *      imap.cpp
 *
 *      Copyright 2009 Sebastian Wankerl <far_away@online.de>
 *
 *      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, write to the Free Software
 *      Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
 *      MA 02110-1301, USA.
 */


# include "imap.hpp"

imap::imap (const std::string &u, const std::string &pw, const std::string &server, bool ssl)  :  base_io (u, pw, server, ssl ? 993 : 143, ssl)
{
    user = u;
    password = pw;
}

imap::~imap () {
    result = close(st);
    if (result == 1)
        throw std::runtime_error ("close () failed");
}

int imap::start () {
    std::string request;
    int counter = 0;
    for (int i = 0; i <= 4; ++i) {
		int temp = recieve(i);
        counter = temp > 0 ? temp : counter;
		if (i == 4)
			break;

        switch (i) {
            case 0: request = "a001 login " + user + " " + password; break;
            case 1: request = "a002 status inbox (unseen)"; break;
			case 2: request = "a003 select inbox"; break;
			case 3: request = "a004 search unseen"; break;
        }
        request += "\r\n";
        send_request (request);
    }
    return counter;
}

int imap::recieve (int step) {
	line.str("");
    int unred_mails = 0;
    for (char c; ssl ? gnutls_record_recv (session, &c, 1) : recv (st, &c, 1, 0) > 0; line << c) {
        if (c == '\n' && (line.str().find("a00") != std::string::npos || step == 0)) {
            if (step == 2) {
                unred_mails = procedure_string(line.str());
                return unred_mails;
            }
			if (step == 4) {
				find_unred_mails(line.str());
				break;
			}
            else
                break;
        } else if (c == '\n' && line.str().find("BAD") != std::string::npos)
			throw std::runtime_error ("Access denied");
    }
    return 0;
}

int imap::procedure_string (std::string str) {
    int counter = 0;
    unsigned index = str.find ("UNSEEN");
    if (index != std::string::npos) {
        std::string count_str = str.substr (str.find (' ', index) + 1, str.size () - index - 9);
        counter = atoi(count_str.c_str());
    }
    return counter;
}

void imap::find_unred_mails (std::string line) {
	boost::erase_head(line, 9);
	boost::erase_tail(line, line.length()-line.find('\n')+1);
	if (line.length() > 0)
		boost::split(unred_mails, line, boost::is_any_of(" "));
}

bool imap::get_header(std::string &str, unsigned pos) {
	if (pos < unred_mails.size()) {
		std::string request = "a005 fetch " + unred_mails[pos] + " body[header]\r\n";
		send_request(request);
		recieve(5);

		str = line.str();
		return true;
	}
	return false;
}

void imap::set_unred(int pos) {
	std::string request = "a006 store " + unred_mails[pos] + " -flags \\seen\r\n";
	send_request(request);
	recieve(6);
}
