#include "IMFMessage.h"
#include "IMFHeader.h"
#include "IMFMultipart.h"
#include "IMFPlainText.h"
#include "Log.h"

namespace coreutils {

   IMFMessage::IMFMessage() : ZString() {
   }

   IMFMessage::IMFMessage(ZString &in) : ZString(in) {

      while (!in.ifNext("\r\n")) {
	 headers.emplace_back(in);
      }

      ZString type = getHeader("Content-Type");
      int len = getHeader("Content-Length").asInteger();
      if(len > 0) {
         ZString block = in.readBlock(len);
         if(type.equals("multipart/form-data"))
   	     body = new IMFMultipart(block, getHeaderKeyPairValue("Content-Type", "boundary"));
         else if(type.equals("text/plain"))	   
	   body = new IMFPlainText(block);
         else
	   body = new IMFBody(block);	 
      }
   }

   void IMFMessage::output(std::stringstream &out) {
      for(IMFHeader header: headers) {
         out << header.getKey() << ": " << header.getValue() << "\r\n";
      }
      out << "\r\n";
   }

   void IMFMessage::addHeader(ZString key, ZString value) {
      headers.emplace_back(key, value);
   }

   void IMFMessage::addHeader(const char *key, ZString value) {
      headers.emplace_back(ZString(key), value);
   }

   ZString IMFMessage::getHeader(ZString key, bool valueOnly) {
      for(IMFHeader header: headers) {
         if(header.getKey().equals(key)) {
	         ZString value = header.getValue();
	         if(valueOnly) {
	            std::vector<ZString> split = ZString(value).split(";");
	            value = split[0];
	         }
	    return value;
         }
      }
      return ZString();
   }

   ZString IMFMessage::getHeaderKeyPairValue(const char *headerKey, const char *key) {
      return getHeaderKeyPairValue(ZString(headerKey), ZString(key));
   }

   ZString IMFMessage::getHeaderKeyPairValue(ZString headerKey, ZString key) {
      ZString value;
      ZString psource(getHeader(headerKey, false));
      std::vector<ZString> sourcep = psource.split(";");
         for(ZString work: sourcep) {
         work.skipWhitespace();
         ZString token = work.getTokenExclude("=");
         if(work.ifNext((char *)"=")) {
            if(token.equals(key)) {
               if(work.ifNext((char *)"\"")) {
                  value = work.getTokenExclude((char *)"\"");
                  return value;
               }
               else {
                  value = work;
                  return value;
               }
            }
            else
              continue;

         } else if (work.ifNext((char *)";") || work.ifNext((char *)" ")) {
            if(token.equals(key))
              return ZString((char *)"true");
            else
              continue;

         }
      }
      return ZString((char *)"false");
   }

   IMFBody * IMFMessage::getBody() {
      return body;
   }

}
