/*!
  \param path The QFileInfo of the path to open (it can be a file, a folder, a symlink,...).
  \param source The place where the path was found.
  \param sourceIsAContainerFile Indicates if "source" is a container file.
  \return Returns a ResultOfOpening value indicating the result of the operation.
*/
TNxSpooler::ResultOfOpening TNxSpooler::openPath(QFileInfo &path, const QString &source, bool /* sourceIsAContainerFile (temporary unused parameter) */) const
{
   QDEBUG_METHOD_NAME;

   // Object to store the arguments to some callings
   QStringList arguments;

   // Name of the application that can be used to open the file
   QString app;

   // Stores the result of opening the path. This will be the value to return
   TNxSpooler::ResultOfOpening opResult = TNxSpooler::OpeningError; // It has this default value

   // Folders and {paths that do not seem to exist (there are many cases)} are not managed in the next block
   if (!path.isDir() && path.exists())
   {
      // Get the index of the file extension
      int i = m_settings.value("exts").toStringList().indexOf(path.suffix());

      if (i == -1)
      {
         // This case can happen if the path to open was inside a container file
         syst.showError(tr("2208097 - NxSpooler is not configured to launch an application to open files "
                              "like \"%1\", which was found inside \"%2\".\n\n"
                              "The administrator of this computer should see if this is due to a mistake "
                              "of the program that created the file, an incorrect configuration of "
                              "NxSpooler, etc.")
                              .arg(QDir::toNativeSeparators(path.fileName()))
                              .arg(QDir::toNativeSeparators(source)));

         return TNxSpooler::OpeningError;
      }

      app = m_settings.value("apps").toStringList().value(i);
      // There's no problem if app.isEmpty()

#ifdef Q_WS_WIN
      arguments << "/C" << "start" << "/wait" << app;
#endif
   }

   // Note: this way it worked with paths like "smb://server/resource" in Linux
   arguments << QDir::toNativeSeparators(path.filePath());

   // Folders and {paths that do not seem to exist (there are many cases)} are not managed in the next block
   if (path.exists() && !path.isDir())
   {
      // For avoiding the problem of having a file still being formed
      // and trying to open it, we'll wait until it has a stable size

      path.setCaching(false); // To try to read the current information about the file
      qint64 file_size_in_instant_1, file_size_in_instant_2;

      do
      {
         // Get the size
         file_size_in_instant_1 = path.size();

         syst.wait(750);

         // Refresh the information that we have about the file
         path.refresh();

         file_size_in_instant_2 = path.size();
      } while (file_size_in_instant_1 != file_size_in_instant_2);

      // Try to open the file
#ifdef Q_WS_WIN
      if (syst.execute("cmd", arguments) == 0)
          opResult = TNxSpooler::OpeningOk;
      else
          opResult = TNxSpooler::OpeningError;
#else
      // If the user is using Linux and he has not specified the name of the program to use,
      // execute the default program
      if (app.isEmpty())
      {
         if (syst.execute(getDefaultProgramInLinux(), arguments) == 0)
            opResult = TNxSpooler::OpeningOk;
         else
            opResult = TNxSpooler::OpeningError;
      }
      else
      {
         if (syst.execute(app, arguments) == 0)
            opResult = TNxSpooler::OpeningOk;
         else
            opResult = TNxSpooler::OpeningError;
      }
#endif
   }
   else
   {
      // it's a folder, or something that doesn't seem to exist (there are many cases)

#ifdef Q_WS_WIN
      // Windows explorer has anti-standard behaviours: for example returning 1 if it could
      // open a file and also returning the same value in some cases that it couldn't
      if (syst.execute("explorer", arguments) == 1)
         opResult = TNxSpooler::OpeningOk;
      else
         opResult = TNxSpooler::OpeningError;
#else
      if (syst.execute("xdg-open", arguments) == 0)
         opResult = TNxSpooler::OpeningOk;
      else
         opResult = TNxSpooler::OpeningError;
#endif
   }

   return opResult;
}