/***************************************************************************
**
**  This file is part of QGpGuiTools.
**
**  This library is free software; you can redistribute it and/or
**  modify it under the terms of the GNU Lesser General Public
**  License as published by the Free Software Foundation; either
**  version 2.1 of the License, or (at your option) any later version.
**
**  This file is distributed in the hope that it will be useful, but WITHOUT
**  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
**  FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
**  License for more details.
**
**  You should have received a copy of the GNU Lesser General Public
**  License along with this library; if not, write to the Free Software
**  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
**
**  See http://www.geopsy.org for more information.
**
**  Created: 2007-02-08
**  Copyright: 2007-2019
**    Marc Wathelet
**    Marc Wathelet (LGIT, Grenoble, France)
**
***************************************************************************/

#include "Application.h"
#include "BugReport.h"
#include "GuiMessage.h"

namespace QGpGuiTools {

/*!
  \class Application Application.h
  \brief Brief description of class still missing

  Full description of class still missing
*/

/*!
  Description of constructor still missing
*/
Application::Application(int & argc, char ** argv, ApplicationHelp * ( *help) (), bool reportBugs, bool setPath)
    : CoreApplicationPrivate(argc, argv, setPath),
#if(QT_VERSION > QT_VERSION_CHECK(5, 0, 0))
      // Qt 5 no longer supports the GUIenabled flag
      QApplication(argc, argv)
#else
      QApplication(argc, argv, hasGui())
#endif
{
  // Qt application information
  setApplicationName(CoreApplicationPrivate::constructorApplicationName());
  setOrganizationDomain("geopsy.org");
  setOrganizationName("geopsy");
  // Install message handler
  setMessageHandler(new GuiMessage);
  setQuitOnLastWindowClosed(true);
  // load translation if necessary
  initTranslations();
  setBatch(false);    // Gui application are by default not in batch

  // Check arguments
  int i, j=1;
  for(i=1; i<argc; i++) {
    QByteArray arg=argv[i];
    if(arg=="-reportbug") {
      reportBug();
      ::exit(0);
    } else if(arg=="-reportint") {
      reportInterrupt();
      ::exit(0);
    } else if(help && (arg=="--help" || arg=="-help" || arg=="-h")) {
      showHelp(i, argc, argv, help);
      ::exit(0);
    } else if(arg=="-batch") {
      setBatch(true);
    } else if(arg=="-args") {
      int max=50;
      if(checkOptionArg(i, argc, argv, false)) {
        max=atoi(argv[i]);
      }
      printArgumentLists(max);
      ::exit(0);
    } else if(arg=="-qt-plugin-paths") {
      // Need a fully constructed QCoreApplication
      printLibraryPaths();
      ::exit(0);
    } else if(arg=="-rargs") {
      int index=0;
      if(checkOptionArg(i, argc, argv, false)) {
        index=atoi(argv[i]);
      }
      ::exit(startArgumentList(index));
    } else if(arg=="--nobugreport" || arg=="-nobugreport") {
      reportBugs=false;
    } else {
      argv[j++]=argv[i];
    }
  }
  if(j<argc) {
    argv[j]=nullptr;
    argc=j;
  }

  initInternalDebugger(reportBugs);
  checkAtomicOperations();
  // Application name and organisation are properly set, we can use settings
  updateArgumentLists();
}

/*!
  Description of destructor still missing
*/
Application::~Application()
{
  // Clearing the clicpboard is apparently required under Windows Xp, else it hangs on exit
  if(hasGui()) {
    clipboard()->clear();
  }
  destructorCleanUp();
}

bool Application::hasGui() const
{
#if defined(Q_OS_WIN) || defined(Q_OS_MAC)
  return true;
#else
  const char * display=getenv("DISPLAY");
  return display && strlen(display)>0;
#endif
}

/*!
  In gui applications with command line option, it allows to remove any gui message box
*/
void Application::setConsoleMessage()
{
  setMessageHandler(new Message);
}

/*!
  In gui applications with commad line option, it allows to restore a gui message box
*/
void Application::setGuiMessage()
{
  setMessageHandler(new GuiMessage);
}

void Application::reportBug()
{
  if(hasGui()) {
    BugReport * d=new BugReport;
    d->setInfo(getStdin());
    d->exec();
    delete d;
  } else {
    App::log(tr("\nPlease copy the message below to http://www.geopsy.org/bugs/backtrace.php:\n\n"));
    App::log(getStdin()+"\n");
    App::log(tr("Please copy the above message to http://www.geopsy.org/bugs/backtrace.php.\n"
                "Only the XML content must be copied: <CrashReport>...</CrashReport>\n"
                "This is the system information to copy in the first field of this online form.\n"));
  }
}

void Application::reportInterrupt()
{
  // Ask if it is stalled or just an interrupt
  askForUserInterrupt();
  reportBug();
}

/*!
  
*/
void Application::setHelp(ApplicationHelp * h)
{
  h->addGroup(tr("Qt"), "qt", 6);
  h->addOption(tr("-nograb"), tr("Tells Qt that it must never grab the mouse or the keyboard"));
#ifdef Q_OS_UNIX
  h->addOption(tr("-dograb"), tr("Running under a debugger can cause an implicit -nograb, use -dograb to override"));
  h->addOption(tr("-sync"), tr("Switches to synchronous mode for debugging"));
#endif
  h->addOption(tr("-style <style>"), tr("Sets the application GUI style. Possible values are\n"
                                        "  motif\n"
                                        "  windows\n"
                                        "  platinum\n"
                                        "If you compiled Qt with additional styles or have additional styles as plugins "
                                        "these will be available to the -style command line option"));
  h->addOption(tr("-session <session>"), tr("Restore the application from an earlier session"));
  h->addOption(tr("-reverse"), tr("Sets the application's layout direction to right to left"));
#ifdef Q_OS_UNIX
  h->addOption(tr("-display <display>"), tr("Sets the X display (default is $DISPLAY)"));
  h->addOption(tr("-geometry <geometry>"), tr("Sets the client geometry of the first window that is shown"));
  h->addOption(tr("-fn, -font <font>"), tr("Defines the application font. The font should be specified using an X logical "
                                          "font description"));
  h->addOption(tr("-bg, -background <color>"), tr("Sets the default background color and an application palette (light and dark "
                                                 "shades are calculated)"));
  h->addOption(tr("-fg, -foreground <color>"), tr("Sets the default foreground color"));
  h->addOption(tr("-btn, -button <color>"), tr("Sets the default button color"));
  h->addOption(tr("-name <name>"), tr("Sets the application name"));
  h->addOption(tr("-title <title>"), tr("Sets the application title"));
  h->addOption(tr("-visual TrueColor"), tr("Forces the application to use a TrueColor visual on an 8-bit display"));
  h->addOption(tr("-ncols <count>"), tr("Limits the number of colors allocated in the color cube on an 8-bit display, if the "
                                        "application is using the QApplication::ManyColor color specification. If count is 216 then a "
                                        "6x6x6 color cube is used (i.e. 6 levels of red, 6 of green, and 6 of blue); for other values, "
                                        "a cube approximately proportional to a 2x3x1 cube is used"));
  h->addOption(tr("-cmap <count>"), tr("Causes the application to install a private color map on an 8-bit display"));
  h->addOption(tr("-im <XIM server>"), tr("Sets the input method server (equivalent to setting the XMODIFIERS environment variable)"));
  h->addOption(tr("-noxim"), tr("Disables the input method framework (\"no X input method\")"));
  h->addOption(tr("-inputstyle <inputstyle>"), tr("Defines how the input is inserted into the given widget. Possible values are:\n"
                                                 "  onTheSpot makes the input appear directly in the widget\n"
                                                 "  offTheSpot\n"
                                                 "  overTheSpot makes the input appear in a box floating over the widget"));
#endif
  CoreApplicationPrivate::setHelp(h);
}

} // namespace QGpGuiTools
