#include <unistd.h>
#include <QLabel>
#include <QSplashScreen>
#include <QApplication>
//#include <QDesktopWidget>
#include <QLocale>
#include "QFitsGlobal.h"
#include "QFitsMainWindow.h"
#include "qtdpuser.h"
#include "dpuser_utils.h"

extern "C" {
#include "resources/splash.xpm"
}

#include "dialogs.h"

// eventually add following if encontering xcb problems
// (requires installation of package 'libicu-dev' and
// configuration of qt without following options: -no-icu -no-dbus)
//Q_IMPORT_PLUGIN(QXcbIntegrationPlugin)

#ifdef WIN
#include <direct.h>
#endif /* WIN */

#ifdef Q_WS_X11
#include <QMotifStyle>
#endif /* Q_WS_X11 */

QSplashScreen *gsplash = NULL;

// handler to open files at startup
void openFileStartup(QString fname, int i) {
    if (gsplash) gsplash->close();
    qApp->restoreOverrideCursor();
    fname.replace("\\", "/");
    if (fname.endsWith("]")) {
        // deal with FITS extensions
        QString extStr = fname.mid(fname.lastIndexOf("[") + 1, fname.length() - fname.lastIndexOf("[") - 2);
        if (extStr == "*") {
            dpuser_widget->executeCommand(QString("buffer") + QString::number(i) + " = readfitsall(\"" + fname.left(fname.lastIndexOf("[")) + "\")");
        } else {
            int extNum = extStr.toInt();
            if (extNum > 0) {
                dpuser_widget->executeCommand(QString("buffer") + QString::number(i) + " = readfitsextension(\"" + fname.left(fname.lastIndexOf("[")) + "\", " + QString::number(extNum) + ")");
            } else if (extNum == 0) {
                dpuser_widget->executeCommand(QString("buffer") + QString::number(i) + " = readfits(\"" + fname.left(fname.lastIndexOf("[")) + "\")");
            }
        }
    } else {
        Fits _tmp;
        QByteArray s = fname.toLocal8Bit();
        int numExtensions = _tmp.CountExtensions(s.constData());
        if (numExtensions < 1) {
            dpuser_widget->executeCommand(QString("buffer") + QString::number(i) + " = readfits(\"" + fname + "\")");
        } else {
            // show Advanced Dialog
            dpFitsExtensionDialog *dialog = new dpFitsExtensionDialog(NULL, fname, i!=1, TRUE);
            dialog->exec();
        }
    }

    QFileInfo finfo;
    finfo.setFile(fname);
    settings.lastOpenPath = finfo.absoluteDir().path();
    settings.lastOpenPath.replace("\\", "/");
}

// This is needed to enable drag & drop files on the app-icos on MacOSX
#ifdef Q_OS_MAC
#include <QString>
#include <QStringList>
#include <QFileOpenEvent>
bool macos_fitsLoadedInMain;

class QMacApplication : public QApplication
{
public:
    QMacApplication(int &argc, char **argv) : QApplication(argc, argv) {
        // handle here file-arguments from command line
        // store filenames for later handling
        for (int i = 1; i < argc; i++) {
            cmdList.append(argv[i]);
        }
    }

protected:
    virtual bool event(QEvent * event ) {
        // handle here file-arguments from drag-and-drop in Finder
        // The FileOpen-event can be emitted asynchronously, so handle
        // it right here if it hasn't been handled in main() already
        if (event->type() == QEvent::FileOpen) {
            cmdList.append(static_cast<QFileOpenEvent*>(event)->file());
            if (macos_fitsLoadedInMain) {
                openFileStartup(cmdList.last(), cmdList.size());
            }
        }
        return QApplication::event(event);
    }
public:
    QStringList cmdList;
};
#endif

#ifdef WIN
#ifdef STATICQT
int main(int argc, char **argv) {
#else // STATICQT
int main(int argc, char **argv) {
#endif // STATICQT
#else // WIN
int main(int argc, char **argv) {
#endif // WIN
    if (!settings.dpuserlibPath.isEmpty()) {
        dpString env;
        env = "DPUSER=";
        env += settings.dpuserlibPath.toStdString();
        putenv(strdup(env.c_str()));
    }
    if (getenv("DPUSER") == NULL) {
        char *cwd = (char *)malloc(256 * sizeof(char));
        if (cwd != NULL) {
            getcwd(cwd, 255);
            char *env = (char *)malloc((strlen(cwd) + 20) * sizeof(char));
            if (env != NULL) {
                sprintf(env, "DPUSER=%s/dpuserlib", cwd);
                putenv(env);
            }
            free(cwd);
        }
    }
    init_dpplplot();

#ifdef Q_OS_MAC
    macos_fitsLoadedInMain = false;
//    if (QSysInfo::MacintoshVersion > QSysInfo::MV_10_8) {
        // fix Mac OS X 10.9 (mavericks) font issue
        // https://bugreports.qt-project.org/browse/QTBUG-32789
//        QFont::insertSubstitution(".Lucida Grande UI", "Lucida Grande");
//    }

//    QMacApplication::setColorSpec(QMacApplication::CustomColor);
//    QMacApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true);
    QMacApplication a(argc, argv);
#else
//    QApplication::setColorSpec(QApplication::CustomColor);
//    QApplication::setAttribute(Qt::AA_EnableHighDpiScaling, true);
//    QApplication::setAttribute(Qt::AA_DisableHighDpiScaling, true);
    QApplication a(argc, argv);
#endif
/*
    QFont tf = a.font();
    double ps = tf.pointSizeF();
    tf.setPointSizeF(ps);
    a.setFont(tf);
*/
#ifdef WIN
    a.setStyle(QStyleFactory::create("Fusion"));
#endif /* WIN */
    QSplashScreen splash(QPixmap((const char **)splash_xpm));
    gsplash = &splash;
    splash.show();

    QLocale::setDefault(QLocale::c());
    qtinputmutex = new QMutex();
    dpusermutex = new QMutex();
    appDirPath = a.applicationFilePath();

    // Create splash screen

    // if called with an argument, we will load an image - print that out on
    // the splash screen
    if (argc > 1) {
        splash.showMessage(QString("Loading ") + QString(argv[1]) + "...", Qt::AlignBottom);
    }

    QFitsMainWindow main_widget;
    fitsMainWindow = &main_widget;
    main_widget.setWindowTitle("QFitsView");
    main_widget.StartDpuser();

    if (dpuser_widget) {
        dpuser_widget->executeCommand("buffer1 = fits(256, 256)");
    }

    // attempt to load the image if called with an argument
#ifdef Q_OS_MACX
    if (a.cmdList.size() > 0) {
        // on Mac finish the SplashScreen already here because it stays on top if
        // a multiextension file has been provided (the splah hides the FileExtension-dialog...)
        splash.close();
        for (int i = 0; i < a.cmdList.size(); i++) {
            openFileStartup(a.cmdList.at(i), i+1);
        }
    }
    QMacApplication::setOverrideCursor(Qt::WaitCursor);
    macos_fitsLoadedInMain = true;
#else
    if (argc > 1) {
        splash.close();
        for (int i = 1; i < argc; i++) {
            openFileStartup(argv[i], i);
        }
    }
    QApplication::setOverrideCursor(Qt::WaitCursor);
#endif

    main_widget.resize(settings.width, settings.height);
    if (settings.maximized) {
        main_widget.showMaximized();
    } else {
        main_widget.show();
    }

    splash.finish(fitsMainWindow);
#ifdef Q_OS_MAC
    QMacApplication::restoreOverrideCursor();
#else
    QApplication::restoreOverrideCursor();
#endif

    return a.exec();
}

//#ifdef Q_WS_MAC
//
//  /* Very Dirty - make this work on MacOS Tiger */
//  /* FIXME: remove once we compile on Snow Leopard */
//#include <Carbon.h>
//static OSErr checkAppleEventForMissingParams(const AppleEvent&theAppleEvent);
//static pascal OSErr odocHandler(const AppleEvent* inEvent, AppleEvent* /*reply*/, long /*refCon*/);
//  //extern "C" { void *__dso_handle = NULL; }
//
//    AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
//                          NewAEEventHandlerUPP(odocHandler),0,false);
//    //      Eventually we should handle 'pdoc' events as well.
//    //
//    //AEInstallEventHandler(kCoreEventClass,kAEPrintDocuments,
//    //                      NewAEEventHandlerProc(handle_print_documents),0,false);
//
//static OSErr checkAppleEventForMissingParams(const AppleEvent&theAppleEvent) {
//    DescType returnedType;
//    Size actualSize;
//    OSErr err;
//
//    switch (err = AEGetAttributePtr(&theAppleEvent, keyMissedKeywordAttr,
//                                    typeWildCard, &returnedType, nil, 0,
//                                    &actualSize))
//    {
//        case errAEDescNotFound:          // If we couldn't find the error attribute
//            return noErr;                //    everything is ok, return noErr
//        case noErr:                      // We found an error attribute, so
//            return errAEEventNotHandled; //    tell the client we ignored the event
//        default:                         // Something else happened, return it
//            return err;
//    }
//}
//
//static pascal OSErr odocHandler(const AppleEvent* inEvent,
//                                AppleEvent* /*reply*/, long /*refCon*/)
//{
//    fprintf(stderr, "Handling \'odoc\'\n");
//    AEDescList documentList;
//    OSErr err = AEGetParamDesc(inEvent, keyDirectObject, typeAEList, &documentList);
//    if (err == noErr) {
//        err = checkAppleEventForMissingParams(*inEvent);
//
//        if (err == noErr) {
//            long documentCount;
//            err = AECountItems(&documentList, &documentCount);
//
//            for (long documentIndex = 1; err == noErr && documentIndex <=
//                 documentCount; documentIndex++) {
//                // What kind of document is it?
//                DescType returnedType;
//                Size actualSize;
//                err = AESizeOfNthItem(&documentList, documentIndex, &returnedType,
//                                      &actualSize);
//                if (err == noErr) {
//
//                    // It's just a normal document file
//                    AEKeyword keyword;
//                    FSRef ref;
//                    err = AEGetNthPtr(&documentList, documentIndex, typeFSRef,
//                                      &keyword, &returnedType, (Ptr)&ref,
//                                      sizeof(FSRef), &actualSize);
//
//                    if (err == noErr) {
//                        char buf[1024];
//                        FSRefMakePath(&ref, reinterpret_cast<UInt8*>(buf), 1024);
//                        //static_cast<PSPApp*>(qApp)->openWindowForFile(QString:: fromUtf8(buf));
//                        //dpuser_widget->executeCommand(freeBufferName() + " = readfits(\"" +
//                        //                              QString::fromUtf8(buf).replace("\\", "/") +
//                        //                              "\")");
//                        dpuser_widget->executeCommand("newbuffer \"" +
//                                                      QString::fromUtf8(buf).replace("\\", "/") +
//                                                      "\"");
//                    }
//                }
//            }
//        }
//        AEDisposeDesc(&documentList);
//    }
//    fprintf(stderr, "Returning %d from handleOpenDocuments\n", err);
//    return err;
//}
//
//#endif /* Q_WS_MAC */

