//=========================================================================
//  Copyright (c) Kitware, Inc.
//  All rights reserved.
//  See LICENSE.txt for details.
//
//  This software is distributed WITHOUT ANY WARRANTY; without even
//  the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
//  PURPOSE.  See the above copyright notice for more information.
//=========================================================================
// .NAME qtNewtInterface.h

#ifndef smtk_newt_qtNewtInterface_h
#define smtk_newt_qtNewtInterface_h

#include "smtk/newt/Exports.h"

#include <QByteArray>
#include <QList>
#include <QObject>
#include <QSslError>
#include <QString>

class QNetworkAccessManager;
class QNetworkReply;

namespace newt
{

/**\brief Singleton class for connecting to NERSC using NEWT api.
 */
class SMTKNEWT_EXPORT qtNewtInterface : public QObject
{
  Q_OBJECT

public:
  static qtNewtInterface* instance(QObject* parent = nullptr);
  ~qtNewtInterface() override;

  bool isLoggedIn() const { return m_isLoggedIn; }

  // QString getScratchDir() const;

  // Login to NERSC
  // password argument must be <user-password + MFA-onetime-password>
  void login(const QString& username, const QString& password);

  // Backdoor login **for testing only**
  void mockLogin(const QString& username, const QString& newtSessionId);

  // Parses command reply to return output and/or error message
  void getCommandReply(QNetworkReply* reply, QString& result, QString& error) const;

  QNetworkAccessManager* networkAccessManager() const { return m_networkManager; }

  QString newtSessionId() const { return m_newtSessionId; }

  QNetworkReply* requestDirectoryList(const QString& machine, const QString& path);

  // Start request to get user's $HOME path
  QNetworkReply* requestHomePath(const QString& machine);

  // Start requrest to get user's $SCRATCH path
  QNetworkReply* requestScratchPath(const QString& machine);

  // Start requires to download file
  QNetworkReply* requestTextFile(const QString& machine, const QString& path);

  // Start command request
  QNetworkReply* sendCommand(const QString& command, const QString& machine);

  QString userName() const { return m_username; }

signals:
  void error(const QString& message, QNetworkReply* networkReply);
  void loginComplete(const QString& userName, int lifetime);
  void loginFail(const QString message);

protected slots:
  void onLoginReply();
  void onSslErrors(const QList<QSslError>& errors);

protected:
  qtNewtInterface(QObject* parent = nullptr);

  QString getErrorMessage(QNetworkReply* reply, const QByteArray& bytes) const;
  QNetworkReply* sendGetRequest(const QString& url);

  bool m_isLoggedIn;
  QNetworkAccessManager* m_networkManager;
  QString m_newtSessionId;
  QString m_username;

private:
  Q_DISABLE_COPY(qtNewtInterface);
};

} // namespace newt

#endif
