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

#define CRLF "\r\n"

namespace mail {
      
   int __SMTP_DATA::processCommand(coreutils::ZString &request, core::TCPSession &session) {
	   
       SMTPSession &s = dynamic_cast<SMTPSession &>(session);
	   SMTPServer &server = session.server;

       switch(session.mode) {
	 
        case WAIT_FOR_DATA:
	 
	      switch(session.state) {
	    
	       case RCPT:
	         s.out << "354 Enter the mail message terminated by <CRLF>.<CRLF>" << CRLF;	 
		     s.mailData.str("");
	    	 s.mode = RECEIVE_DATA;
	    	 server.commands.grabInput(&session, *this);		  
	    //	       setTimer(120.0f);
	    	 break;
	    
	  	   case MAIL:
	         s.out << "503 Please use RCPT first" << CRLF;	 
	         break;
	       
	       default:
	         s.out << "503 Please use MAIL first" << CRLF;	 	    
	         break;
	    
	     }
	     break;
	 
       case RECEIVE_DATA:
	     if(request.str() != ".") 
	       s.mailData << request.str() << CRLF;	     	    	    
	     else {		 
	    	s.mode = WAIT_FOR_DATA;  	       
	    	s.state = READY;
	    	server.commands.clearGrab(&session);
	    //	       if(filterMessage(session.mailData)) {	    		    
	     	if(s.recipientList.size() > 0) {		      
	        	if(s.mailData.str().size() > 0) { 
		       		std::string ID = queueMail(server, session.sender, session.recipientList, session.mailData);
		       		if(ID != "") {     
		          	   coreutils::Log(coreutils::LOG_INFO) << "Queued message " << ID << ".";
		          	   s.out << "250 OK Queued message " << ID << CRLF;		  
		            }
		            else		     
		              s.out << "550 Mail message too big" << CRLF; 
	            } else 
		          s.out << "550 Mail message was empty" << CRLF;		   
	        } else 	       
	        s.out << "250 OK Queued message " << CRLF; 
	    //	       } else 	    
	    //		 data << "550 Message is probably spam" << CRLF;
	     }
	    break;	 
     }
     return 1;
   }
   
   std::string __SMTP_DATA::generateMailFileName() {
      std::stringstream temp;
      struct timespec timex;
      clock_gettime(CLOCK_REALTIME, &timex);
      temp << timex.tv_sec << "." << std::setfill('0') << std::setw(9) << timex.tv_nsec; 
      return temp.str();	
   }      
   
   std::string __SMTP_DATA::queueMail(SMTPServer &server, std::string sender, std::vector<std::string> recipientList, std::stringstream &mailData) { 
      std::string fileName = server.mailFileSystem.getMailPath() + "/.queue/" + generateMailFileName();
      coreutils::File mailFile(fileName, O_CREAT | O_WRONLY, 0660);
      mailFile.write(mailData.str());      

      for(std::string recipient: recipientList) {
	     std::string newName = fileName + recipient;
	    link(fileName.c_str(), newName.c_str());
      }
      
      unlink(fileName.c_str());
      
      return fileName;
   }

}

      