#include "wxinc.h"
#include "xvt.h"

#include "smapi.h"
#include <wx/tokenzr.h>
#include <wx/file.h>
#include <wx/filename.h>
#include <wx/mimetype.h>

static wxString GetMailParam(const char* key, const char* def = "")
{
  static wxString ini;  // C:\campo\dati\config\user.ini
    
  if (ini.IsEmpty())
  {
    wxString cu = "ADMIN";
    for (int i = __argc-1; i > 1; i--)
    {
      wxString u = __argv[i]; u.MakeUpper();
      if (u.StartsWith("/U") || u.StartsWith("-U"))
      {
        cu = u.Mid(2);
        break;
      }
    }

    char study[_MAX_PATH]; xvt_sys_get_profile_string(NULL, "Main", "Study", "", study, sizeof(study));
    ini = study; 
    if (!wxEndsWithPathSeparator(ini))
      ini += wxFILE_SEP_PATH;
    ini += "config\\"; ini += cu; ini += ".ini";
  }
  wxString val; const size_t sz = _MAX_PATH;
  xvt_sys_get_profile_string(ini, "Mail", key,  def, val.GetWriteBuf(sz), sz); 
  val.UngetWriteBuf();
  return val;
}

static bool GetMailParams(wxString& smtp, wxString& port, wxString& user, wxString& pass, wxString& from)
{
  smtp = GetMailParam("Server", "MAPI");
  port = GetMailParam("Port");
  user = GetMailParam("User");
  pass = GetMailParam("Password");
  wxString f = user; 
  if (f.find('@') < 0) 
  { f += "@"; f += smtp.AfterFirst('.'); }
  from = GetMailParam("From", f);

  return !smtp.IsEmpty() && !pass.IsEmpty();
}

short xvt_mail_installed()
{
   short bInstalled = 0;

   if (::GetProfileInt(_T("MAIL"), _T("MAPI"), 0) != 0 && 
       SearchPath(NULL, _T("MAPI32.DLL"), NULL, 0, NULL, NULL) != 0)
     bInstalled |= 0x1;

   if (xvt_fsys_file_exists("servers/mailsend.exe"))
   {
     wxString smtp, port, user, pass, from;
     GetMailParams(smtp, port, user, pass, from);
     if (!pass.IsEmpty() && smtp != "MAPI")
       bInstalled |= 0x2;
   }

   return bInstalled;
}

static void AppendQuotedString(wxString& cmd, const char* key, const wxString& value)
{
  if (!value.IsEmpty())
    cmd << " -" << key << " \"" << value << "\"";
}

static void AppendAttachment(wxString& cmd, const wxString& fname, bool att = true)
{
  if (wxFileName::FileExists(fname))
  {
    char ext[_MAX_EXT] = { 0 };
    xvt_fsys_parse_pathname (fname, NULL, NULL, NULL, ext, NULL);
    wxString mime = ext; 
    wxFileType* ft = wxTheMimeTypesManager->GetFileTypeFromExtension(mime);
    if (ft != NULL)
    {
      wxArrayString aMime; 
      if (ft->GetMimeTypes(aMime))
        mime = aMime[0];
    }

    if (att)
    {
      wxString a; a << fname << "," << mime << ",a";
      AppendQuotedString(cmd, "attach", a);
    }
    else
    {
      wxString a; a << fname << "," << mime << ",i";
      AppendQuotedString(cmd, "attach", a);
    }
  }
}


BOOLEAN xvt_mail_send(const char* to, const char* cc, const char* ccn,
                      const char* subject, const char* msg, 
                      const char* attach, short flags)
{  
  bool ui = (flags & 0x1) != 0;

  wxStringTokenizer tokTo(to, _T(";"));
	wxMailMessage Msg(subject, tokTo.GetNextToken(), msg);

  if (flags & 0x2)
    Msg.m_query_receipt = true;

	while (tokTo.HasMoreTokens())
		Msg.AddTo(tokTo.GetNextToken());
  if (Msg.m_to[0].IsEmpty()) 
  {
    Msg.m_to[0] = " "; // Il destinatario "" fa piantare MAPI con errore 25
    ui = true;         // Forza user interface in assenza di recipient
  }

  if (attach && *attach)
  {
    wxStringTokenizer tokAttach(attach, _T(";"));
    while (tokAttach.HasMoreTokens())
		  Msg.AddAttachment(tokAttach.GetNextToken());
  }

  if (cc && *cc)
  {
    wxStringTokenizer Tok(cc, _T(";"));
    while (Tok.HasMoreTokens())
		  Msg.AddCc(Tok.GetNextToken());
  }

  if (ccn && *ccn)
  {
	  wxStringTokenizer Tok(ccn, _T(";"));
    while (Tok.HasMoreTokens())
		  Msg.AddBcc(Tok.GetNextToken());
  }

  const short mail_inst = xvt_mail_installed();
  
  BOOLEAN ok = FALSE;

  wxString server, port, user, password, from;
  if ((mail_inst & 0x2) && GetMailParams(server, port, user, password, from))
  {
    wxString cmd = "servers/mailsend.exe";
    AppendQuotedString(cmd, "smtp", server);
    if (!port.IsEmpty())
    {
      cmd += " -port "; 
      cmd += port;
    }
    AppendQuotedString(cmd, "from", from);

    if ((flags | 0x2) && from.Find("@") > 0)
    {
      //AppendQuotedString(cmd, "rt", from);
      AppendQuotedString(cmd, "rrr", from);
    }

    // Lista dei destinatari
    for (size_t i = 0; i < Msg.m_to.size(); i++)
      AppendQuotedString(cmd, "to", Msg.m_to[i]);

    // Lista dei destinatari in copia
    for (size_t i = 0; i < Msg.m_cc.size(); i++)
      AppendQuotedString(cmd, "cc", Msg.m_cc[i]);  
    if (cmd.Find("-cc") < 0)
      cmd += " +cc"; // In assenza di destinatari in copia aggiungo +cc

    // Lista dei destinatari in copia nascosta
    for (size_t i = 0; i < Msg.m_bcc.size(); i++)
      AppendQuotedString(cmd, "bc", Msg.m_bcc[i]);  
    if (from.Find("@") > 0)
    {
      wxString strMyself; strMyself << "c " << from;
      if (cmd.Find(strMyself) < 0)
        AppendQuotedString(cmd, "bc", from);   // Aggiungo me stesso ai destinatari nascosti
    }
    if (cmd.Find("-bc") < 0)
      cmd += " +bc"; // In assenza di destinatari nascosti aggiungo +bc

    AppendQuotedString(cmd, "sub", Msg.m_subject);
    AppendQuotedString(cmd, "user", user);
    AppendQuotedString(cmd, "pass", password);

    AppendQuotedString(cmd, "enc-type", "base64");

    if (!Msg.m_attachments.IsEmpty())
    {
      for (size_t a = 0; a < Msg.m_attachments.size(); a++)
      {
        const wxString& fn = Msg.m_attachments[a];
        if (wxFileName::FileExists(fn))
          AppendAttachment(cmd, fn);
      }
    }

    wxString ftmp;
    if (Msg.m_body.IsEmpty())
    {
      if (cmd.Find("-M ") < 0)
      {
        wxString m; m << "Cordiali saluti\n" << from;
        m.Trim();
        AppendQuotedString(cmd, "M", m);
      }
    }
    else
    {
      wxStringTokenizer tok(Msg.m_body, "\n");
      Msg.m_body.Trim();
      if (Msg.m_body.Find("\n") < 0)
        AppendQuotedString(cmd, "M", Msg.m_body);
      else
      {
        DIRECTORY tmp; xvt_fsys_get_temp_dir(&tmp);
        xvt_fsys_build_pathname(ftmp.GetWriteBuf(_MAX_PATH), NULL, tmp.path, "msgbody", "html", NULL);
        ftmp.UngetWriteBuf();
        wxFile file(ftmp, wxFile::write);
        file.Write("<html><body>\n");
        Msg.m_body.Replace("\n", "<br>");
        file.Write(Msg.m_body);
        file.Write("\n</body><html>\n");
        file.Close();
        AppendAttachment(cmd, ftmp, false);
      }
    }

    const wxString strLog = "mailsend.log";
    xvt_fsys_remove_file(strLog);
    AppendQuotedString(cmd, "log", strLog);

    int nRetry = wxAtoi(GetMailParam("Retry", "2"));
    if (nRetry <= 0) nRetry = 2;

    ok = FALSE;
    for (int r = 0; r < nRetry && !ok; r++)
    {
      if (r > 0)
      {
        const int nSeconds = 5*r;
        WINDOW w = xvt_dm_progress_create(TASK_WIN, "MailSend retrying...", nSeconds, TRUE);
        for (int s = 1; s <= nSeconds; s++)
        {
          xvt_sys_sleep(1000);
          xvt_dm_progress_set_status(w, s, nSeconds);
        }
        xvt_dm_progress_destroy(w);
      }
      wxExecute(cmd, wxEXEC_SYNC);
      wxFile fLog(strLog, wxFile::read);
      const wxFileOffset flen = fLog.Length();
      if (flen > 0)
      {
        char* buff = (char*)calloc(flen+8, 1); // zero filled buffer
        fLog.Read(buff, flen);
        if (wxStrstr(buff, "Mail sent successfully"))
          ok = TRUE;
        delete [] buff;
      }
    }
  } else
  if (mail_inst & 1)
  {
    xvt_fsys_save_dir();
    ok = Msg.Send(wxEmptyString, ui);
    xvt_fsys_restore_dir();
  }

  return ok;
}