#include "__SMTP_DATA.h"
#include "SMTPServer.h"
#include "Log.h"
#include <chrono>
#include <iomanip>

namespace mail {

   int __SMTP_DATA::processCommand(coreutils::ZString &request, SMTPSession &session, SMTPServer &server) {

       switch(session.mode) {

        case WAIT_FOR_DATA:

	  switch(session.state) {

	   case RCPT:
	     session.out << "354 Enter the mail message terminated by <CRLF>.<CRLF>" << CRLF;
	     session.mailData = "";
	     session.mode = RECEIVE_DATA;
	     grabInput(session);
//	     session.setTimer(120.0f);
	     break;

	   case MAIL:
	     session.out << "503 Please use RCPT first" << CRLF;
	     break;

	   default:
	     session.out << "503 Please use MAIL first" << CRLF;
	     break;

	  }
	  break;

	case RECEIVE_DATA:
	  if(request != ".") {
	    session.mailData << request << CRLF;
     }
	  else {
	     session.mode = WAIT_FOR_DATA;
	     session.state = READY;
	     clearGrab(session);
	     //	       if(filterMessage(session.mailData)) {
	     if(session.recipientList.size() > 0) {
		if(session.mailData.getLength() > 0) {
		   coreutils::MString ID = queueMail(server, session.from, session.recipientList, session.mailData);
		   if(ID != "") {
		      coreutils::Log(coreutils::LOG_INFO) << "Queued message " << ID << ".";
		      session.out << "250 OK Queued message " << ID << CRLF;
		   }
		   else
		     session.out << "550 Mail message too big" << CRLF;
		} else
		  session.out << "550 Mail message was empty" << CRLF;
	     } else
	       session.out << "250 OK Queued message " << CRLF;
	     //	       } else
	     //		 data << "550 Message is probably spam" << CRLF;
	  }
	      break;
       }
      return 1;
   }

   coreutils::MString __SMTP_DATA::generateMailFileName() {
      struct timespec timex;
      clock_gettime(CLOCK_REALTIME, &timex);
      std::stringstream temp;
		temp << timex.tv_sec << "." << std::setfill('0') << std::setw(9) << timex.tv_nsec;
      return coreutils::MString(temp.str());
   }

   coreutils::MString __SMTP_DATA::queueMail(SMTPServer &server,
                                             coreutils::MString &sender,
                                             std::vector<coreutils::MString> &recipientList,
                                             coreutils::MString &mailData) {
      coreutils::MString fileName;
      fileName << server.mailFileSystem.getMailPath() << "/.queue/" << generateMailFileName();
      coreutils::File mailFile(fileName, O_CREAT | O_WRONLY, 0660);
      mailFile.write(mailData);

      for(coreutils::MString recipient: recipientList) {
	 coreutils::MString newName;
         newName << fileName << "|" << recipient;
	 link(fileName.c_str(), newName.c_str());
      }

      unlink(fileName.c_str());

      return fileName;
   }

}

