/***************************************************************************
                          currentaccount.cpp  -  description
                             -------------------
    begin                : Sun Jan 5 2003
    copyright            : (C) 2003 by Mike K. Bennett
    email                : mkb137b@hotmail.com
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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.                                   *
 *                                                                         *
 ***************************************************************************/

#include "currentaccount.h"

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#include <qdir.h>
#include <qfile.h>
#include <qregexp.h>
#include <qstringlist.h>
#include <qtimer.h>

#include <kapplication.h>
#include <kdebug.h>
#include <klocale.h>
#include <kmdcodec.h>
#include <kprocess.h>
#include <krun.h>

#include "kmessdebug.h"

// Initialize the instance to zero
CurrentAccount* CurrentAccount::instance_(0);

// The constructor
CurrentAccount::CurrentAccount()
 : autoreply_(false),
   externalPort_(0),
   loginTime_(0),
   noEmails_(0),
   status_("FLN")
{
  // Connect the timer's timeout so that it removes the hotmail file
  connect( &fileRemovalTimer_, SIGNAL(           timeout() ),
           this,               SLOT  ( removeHotmailFile() ) );
}



// The destructor
CurrentAccount::~CurrentAccount()
{
#ifdef KMESSDEBUG_CURRENTACCOUNT
  kdDebug() << "DESTROYED CurrentAccount " << endl;
#endif
}



// Receive notice that some emails were added or deleted
void CurrentAccount::changeNoEmails( int change )
{
#ifdef KMESSTEST
  int oldNoEmails = noEmails_;
#endif
  setNoEmails( noEmails_ + change );
#ifdef KMESSTEST
  ASSERT( ( noEmails_ == (  oldNoEmails + change ) ) || ( noEmails_ == 0 ) );
#endif
}



// Copy an account
void CurrentAccount::copyAccount( const Account *account )
{
  // Do the ancestor's copying
  Account::copyAccount( account );
}



// Delete the instance of the contact list
void CurrentAccount::destroy()
{
  delete instance_;
  instance_ = 0;
}



// Return whether or not to autoreply to messages
bool CurrentAccount::getAutoreply() const
{
  return autoreply_;
}



// Return the compose command.
const QString& CurrentAccount::getComposeCommand() const
{
  return composeCommand_;
}



// Return the email URL
const QString& CurrentAccount::getEmailUrl() const
{
  return emailUrl_;
}


// Return the external IP
const QString& CurrentAccount::getExternalIP() const
{
  return externalIP_;
}



// Return the external port
uint CurrentAccount::getExternalPort() const
{
  return externalPort_;
}



// Return the inbox command.
const QString& CurrentAccount::getInboxCommand() const
{
  return inboxCommand_;
}



// Return the number of email in the inbox
int CurrentAccount::getNoEmails() const
{
  return noEmails_;
}



// Read property of int sessionLength.
int CurrentAccount::getSessionLength() const
{
  time_t currentTimeT, t;
  int    currentTime, elapsedTime;
//  int    sessionLength;

  currentTimeT = time(&t);

  currentTime = static_cast<int>(currentTimeT);

  // Calculate the time the user's been connected by local reckoning
  elapsedTime = currentTime - loginTime_;
  return elapsedTime;
}



// Return the user's staus
QString CurrentAccount::getStatus() const
{
#ifdef KMESSDEBUG_CURRENTACCOUNT
    kdDebug() << "CurrentAccount - Returning status of " << status_ << "." << endl;
#endif
  return status_;
}



// Return a singleton instance of the current account
CurrentAccount* CurrentAccount::instance()
{
  // If the instance is null, create a new current account and return that.
  if ( instance_ == 0 )
  {
    instance_ = new CurrentAccount();
  }
  return instance_;
}



// Open hotmail with the given command, url, and folder
void CurrentAccount::openHotmail(const QString& command, const QString& folder, const QString& url)
{
#ifdef KMESSDEBUG_CURRENTACCOUNT
  kdDebug() << "CurrentAccount::openHotmail" << endl;
#endif

  QString    html, filename;
  QFile      hotmailFile;
  bool       openedFile;
  QString   sl, hashWord, cred, login;
  KRun      *run;

  // Create a randomized name for the temporary file
  filename = QDir::home().absPath() + "/" + "kmess_hotmail_tempfile_" + KApplication::randomString(8) + ".html";
  // Attempt to open the file for writing
  hotmailFile.setName( filename );
  openedFile = hotmailFile.open( IO_WriteOnly );
  if ( !openedFile )
  {
    kdDebug() << "CurrentAccount - openHotmail() - Couldn't open temporary hotmail file for writing." << endl;
    return;
  }

  // Add the file to the list of hotmail files
  hotmailFileList_.append( filename );

  if ( url != "" )
  {
    // Produce the md5 credential
    sl.sprintf("%d", getSessionLength());
    hashWord = authorization_ + sl + getPassword();
    KMD5 context(hashWord);
    cred = context.hexDigest();
    login = getHandle();
    login = login.left( login.find("@") );
    // Create the html string that will form the hotmail file.
    html  = " <html>\n";
    html += " <head><noscript>\n";
    html += "  <meta http-equiv=Refresh content=\"0; url=http://www.hotmail.com\">\n";
    html += " </noscript></head>\n";
    html += " <body onload=\"document.pform.submit(); \"> \n";
    html += "  <form name=\"pform\" action=\"" + url + "\" method=\"POST\"> \n";
    html += "   <input type=\"hidden\" name=\"mode\" value=\"ttl\"> \n";
    html += "   <input type=\"hidden\" name=\"login\" value=\"" + login + "\"> \n";
    html += "   <input type=\"hidden\" name=\"username\" value=\"" + getHandle() + "\"> \n";
    html += "   <input type=\"hidden\" name=\"sid\" value=\"" + sid_ + "\">\n";
    html += "   <input type=\"hidden\" name=\"kv\" value=\"" + kv_ + "\"> \n";
    html += "   <input type=\"hidden\" name=\"id\" value=\"" + command + "\"> \n";
    html += "   <input type=\"hidden\" name=\"sl\" value=\"" + sl + "\"> \n";
    html += "   <input type=\"hidden\" name=\"rru\" value=\"" + folder + "\"> \n";
    html += "   <input type=\"hidden\" name=\"auth\" value=\"" + authorization_ + "\"> \n";
    html += "   <input type=\"hidden\" name=\"creds\" value=\"" + cred + "\"> \n";
    html += "   <input type=\"hidden\" name=\"svc\" value=\"mail\"> \n";
    html += "   <input type=\"hidden\" name=\"js\" value=\"yes\"> \n";
    html += "  </form>\n";
    html += " </body> \n";
    html += "</html> \n";
  }
  else
  {
    html  = "<html>\n";
    html += " <head>\n";
    html += "  <title>KMess</title>\n";
    html += " </head>\n";
    html += " <body>\n";
    html += "  " + i18n("You can't login to hotmail with this account.") + "\n";
    html += " </body>\n";
    html += "</html>\n";
  }
  // Write the data to the file and close it.
  hotmailFile.writeBlock( html, html.length() );
  hotmailFile.close();

  // Open the file in the default html viewer
  run = new KRun( filename );

  // Start the timer so that it'll remove the file after, say, 10 seconds
  fileRemovalTimer_.start( 10000, true );
}



// Open hotmail at the compose page with the given contact handle
void CurrentAccount::openHotmailAtCompose(QString contactHandle)
{
#ifdef KMESSDEBUG_CURRENTACCOUNT
  kdDebug() << "CurrentAccount::openHotmailAtCompose" << endl;
#endif

  QString contactEmail, folder;

  if ( getUseHotmail() )
  {
    // The contact's email has to have the @ and . changed.
    contactEmail = contactHandle.replace( QRegExp( "@" ), "%40" );
    contactEmail = contactEmail.replace( QRegExp( "\\." ), "%2e" );
    // For a compose message, the folder had to include the address of the contact
    folder = composeFolder_ + "?mailto=1&to=" + contactEmail;
    // Launch the html
    openHotmail( composeCommand_, folder, composeUrl_);
  }
  else
  {
    startProcess(getEmailCommand() + " " + contactHandle);
  }
}



// Open hotmail at the user's inbox
void CurrentAccount::openHotmailAtInbox()
{
#ifdef KMESSDEBUG_CURRENTACCOUNT
  kdDebug() << "CurrentAccount::openHotmailAtInbox." << endl;
#endif

  if ( getUseHotmail() )
  {
    openHotmail( inboxCommand_, inboxFolder_, inboxUrl_ );
  }
  else
  {
    startProcess(getEmailCommand());
  }
}



// Remove the html file used to get into hotmail from the disk.
void CurrentAccount::removeHotmailFile()
{
  // Delete all the files given in the filename list
  for ( unsigned int i = 0; i < hotmailFileList_.count(); i++ )
  {
    remove( hotmailFileList_[i].latin1() );
  }
  // Clear the file names
  hotmailFileList_.clear();
}



// Set some account information
void CurrentAccount::setAccountInformation( QString authorization, QString kv, QString preferredEmail,
                                            QString sid, bool emailSupported, QString externalIP, uint externalPort )
{
  time_t currentTime, t;
#ifdef KMESSTEST
  bool  goodKv, goodSid;
  kv.toInt(&goodKv);
  sid.toInt(&goodSid);
  ASSERT( goodKv && goodSid );
#endif

  authorization_  = authorization;
  kv_             = kv;
  preferredEmail_ = preferredEmail;
  sid_            = sid;
  externalIP_     = externalIP;
  externalPort_   = externalPort;

  // protected method call
  setEmailSupported(emailSupported);

  // Set the local login time by getting the current time
  currentTime = time(&t);
  loginTime_ = static_cast<uint>(currentTime);
}



// Set whether or not to autoreply to a contact's chat message.
void CurrentAccount::setAutoreply(bool autoreply)
{
  autoreply_ = autoreply;
}



// Set compose properties
void CurrentAccount::setComposeInformation( QString command, QString folder, QString url )
{
  composeCommand_ = command;
  composeFolder_ = folder;
  composeUrl_ = url;
}



// Set inbox properties.
void CurrentAccount::setInboxInformation( QString command, QString folder, QString url )
{
  inboxCommand_ = command;
  inboxFolder_ = folder;
  inboxUrl_ = url;
}



// Set initial email information
void CurrentAccount::setInitialEmailInformation( QString emailUrl, int noEmailsInInbox, int noEmailsInOtherFolders )
{
#ifdef KMESSTEST
  ASSERT( noEmails_ == 0 );
  ASSERT( noEmailsInInbox >= 0 );
  ASSERT( noEmailsInOtherFolders >= 0 );
#endif
  emailUrl_ = emailUrl;
  setNoEmails( noEmailsInInbox );
}



// Set the number of emails
void CurrentAccount::setNoEmails( int noEmails )
{
#ifdef KMESSTEST
  ASSERT( noEmails >= 0 );
#endif
  noEmails_ = noEmails;
  if ( noEmails_ < 0 )
  {
    noEmails_ = 0;
  }
  emit changedNoEmails();
}



// Set the user's status
void CurrentAccount::setStatus( QString status )
{
#ifdef KMESSTEST
  ASSERT(    ( status == "AWY" ) || ( status == "BRB" ) || ( status == "BSY" ) || ( status == "FLN" ) || ( status == "HDN" )
          || ( status == "IDL" ) || ( status == "LUN" ) || ( status == "NLN" ) || ( status == "PHN" ) );
#endif
  if (    ( status == "AWY" ) || ( status == "BRB" ) || ( status == "BSY" )
       || ( status == "FLN" ) || ( status == "HDN" ) || ( status == "IDL" )
       || ( status == "LUN" ) || ( status == "NLN" ) || ( status == "PHN" ) )
  {
    status_ = status;
#ifdef KMESSDEBUG_CURRENTACCOUNT
    kdDebug() << "CurrentAccount - Status set to " << status_ << "." << endl;
#endif
    emit changedStatus();
  }
}



// Start a process
void CurrentAccount::startProcess( QString command )
{
#ifdef KMESSDEBUG_CURRENTACCOUNT
  kdDebug() << "CurrentAccount::startProcess: starting '" << getEmailCommand() << "'." << endl;
#endif

  // Construct a command by simply attaching a the email address to the program name
  KProcess *process = new KProcess();  // auto deletes

  // Add all parameters separately
  QStringList commandItems = QStringList::split(" ", command, false);
  for( QStringList::Iterator it = commandItems.begin(); it != commandItems.end(); ++it )
  {
    *process << *it;
  }

  // Launch it
  bool started = process->start(KProcess::DontCare);

  if(! started)
  {
    kdWarning() << "Failed to start '" << getEmailCommand() << "'!" << endl;
  }
}

#include "currentaccount.moc"
