/* ====================================================================
 * Copyright (c) 2003-2006, 2008 Martin Hauner
 *                               http://subcommander.tigris.org
 *
 * Subcommander is licensed as described in the file doc/COPYING, which
 * you should have received as part of this distribution.
 * ====================================================================
 */

// sc
#include "AuthPromptProvider.h"
#include "DialogHandler.h"
#include "SimplePromptDialog.h"
#include "SslServerTrustPromptDialog.h"
#include "events/DialogEvent.h"
#include "util/Condition.h"

// qt
#include <QtGui/QApplication>
#include <QtGui/QCursor>


///////////////////////////////////////////////////////////////////////////////
//

class SimplePromptHandler : public DialogHandler
{
public:
  SimplePromptHandler( const char* realm, const char* user, bool maysave,
    sc::Condition* cond )
    : _realm(realm), _user(user), _maysave(maysave), _cond(cond), _ok(false),
    _save(false) 
  {
  }

  void run( QWidget* parent )
  {
    SimplePromptDialog* dlg = new SimplePromptDialog( _realm, _user, _maysave, parent );

    QApplication::setOverrideCursor( QCursor(Qt::ArrowCursor) );
    int result = dlg->exec();
    QApplication::restoreOverrideCursor();

    if( result == QDialog::Accepted )
    {
      _ok       = true;
      _username = sc::String((const char*)dlg->getUsername());
      _password = sc::String((const char*)dlg->getPassword());
      _save     = dlg->getSave();
    }

    delete dlg;
    
    _cond->wakeAll();
  }

  bool ok() const
  {
    return _ok;
  }

  const sc::String& username() const
  {
    return _username;
  }

  const sc::String& password() const
  {
    return _password;
  }

  bool save() const
  {
    return _save;
  }

private:
  // in
  const char*    _realm;
  const char*    _user;
  bool           _maysave;
  sc::Condition* _cond;

  // out
  bool       _ok;
  bool       _save;
  sc::String _username;
  sc::String _password;
};

//
///////////////////////////////////////////////////////////////////////////////


class SslServerTrustPromptHandler : public DialogHandler
{
public:
  SslServerTrustPromptHandler( const char* realm, unsigned long failures,
    const svn::AuthPromptProvider::sslServerCertInfo& certinfo, bool maySave,
    sc::Condition* cond )
    : _realm(realm), _failuresIn(failures), _certinfo(certinfo), _maysave(maySave),
      _cond(cond), _ok(false), _failures(0), _save(false)
  {
  }

  void run( QWidget* parent )
  {
    SslServerTrustPromptDialog* dlg = new SslServerTrustPromptDialog( _realm,
      _failuresIn, _certinfo, _maysave, parent );

    QApplication::setOverrideCursor( QCursor(Qt::ArrowCursor) );
    int result = dlg->exec();
    QApplication::restoreOverrideCursor();

    if( result == QDialog::Accepted )
    {
      _ok       = true;
      _save     = dlg->getSave();
      _failures = dlg->getFailures();
    }

    delete dlg;
    
    _cond->wakeAll();
  }

  bool ok() const
  {
    return _ok;
  }

  unsigned long failures() const
  {
    return _failures;
  }

  bool save() const
  {
    return _save;
  }

private:
  // in
  const char*       _realm;
  unsigned long     _failuresIn;
  svn::\
  AuthPromptProvider::\
  sslServerCertInfo _certinfo;
  bool              _maysave;
  sc::Condition*    _cond;

  // out
  bool              _ok;
  unsigned long     _failures;
  bool              _save;
};

//
///////////////////////////////////////////////////////////////////////////////

bool AuthPromptProvider::simplePrompt( const char* realm, const char* username,
  bool maySave, svn::AuthPromptProvider::simpleCredentials& cred )
{
  sc::Condition       cond;
  SimplePromptHandler handler( realm, username, maySave, &cond );

  QApplication::postEvent( qApp->mainWidget(), new DialogEvent(&handler) );

  cond.wait();

  if( ! handler.ok() )
  {
    return false;
  }

  cred._username = handler.username();
  cred._password = handler.password();
  cred._save     = handler.save();

  return true;
}


bool AuthPromptProvider::sslServerTrustPrompt( const char* realm, unsigned long failures,
  const svn::AuthPromptProvider::sslServerCertInfo& certinfo, bool maySave,
  svn::AuthPromptProvider::sslServerTrustCredentials& cred )
{
  sc::Condition               cond;
  SslServerTrustPromptHandler handler( realm, failures, certinfo, maySave, &cond );

  QApplication::postEvent( qApp->mainWidget(), new DialogEvent(&handler) );

  cond.wait();

  if( ! handler.ok() )
  {
    return false;
  }

  cred._save             = handler.save();
  cred._acceptedFailures = handler.failures();
  return true;
}
