#include "ifapp.h"
#include "scaledtoplevel.h"
#include "scrolltoplevel.h"
#include "imagelistitem.h"
#include "catagorymgr.h"
#include "imageutils.h"
#include "uimanager.h"
#include <qdir.h>
#include <qpixmap.h>
#include <qimage.h>
#include <qlabel.h>
#include <kglobal.h>
#include <kconfig.h>
#include <kstddirs.h>
#include <kconfig.h>
#include <klocale.h>
#include <kimageio.h>
#include <kprogress.h>
#include "filelist.h"
#include <qmessagebox.h>

#include <X11/X.h>
#include <X11/Xlib.h>
#include "fullscreen.h" // need to include last - X header conflicts

static KIFApplication* appPtr = NULL;

KIFApplication* kifapp(){return(appPtr);}

GC rubberBandGC;
GC viewFillGC;
int xioErrorHandler(Display *dpy);

// ImageMagick message and progress stubs
extern "C"{
    unsigned int magickMonitor(const char *msg, const off_t value,
                               const long long unsigned int span, ExceptionInfo *)
    {
        if(!appPtr)
            return(true);
        int val = (int)((((float)value)/((float)span))*100.0);
        if(appPtr->magickMessageProgress())
            appPtr->magickMessageProgress()->setValue(val);
        if(appPtr->magickMessageLabel())
            appPtr->magickMessageLabel()->setText(msg);
        appPtr->processEvents();
        return(true);
    }

    void magickWarning(const ExceptionType /*warning*/, const char *reason,
                       const char *description)
    {
        QString str(reason);
        str += "\n";
        str += description;
        QMessageBox::warning(NULL, i18n("Warning!"), str,
                             QMessageBox::Ok, QMessageBox::NoButton);
    }

    void magickError(const ExceptionType /*error*/, const char *reason,
                     const char *description)
    {
        QString str(reason);
        str += "\n";
        str += description;
        QMessageBox::warning(NULL, i18n("Error!"), str,
                             QMessageBox::Ok, QMessageBox::NoButton);
    }

    void magickFatalError(const ExceptionType /*error*/, const char *reason,
                          const char *description)
    {
        QString str(reason);
        str += "\n";
        str += description;
        QMessageBox::critical(NULL, i18n("Error!"), str,
                              QMessageBox::Ok, QMessageBox::NoButton);
    }
}

KIFApplication::KIFApplication(int argc, char **argv)
    : KApplication(argc, argv)
{
    list = NULL;
    catMgr = NULL;
    mplayerWindow = 0;

    Display *dpy = QPaintDevice::x11AppDisplay();
    rubberBandGC = XCreateGC(dpy, DefaultRootWindow(dpy), 0, 0);
    XSetFunction(dpy, rubberBandGC, GXinvert);
    XSetLineAttributes(dpy, rubberBandGC, 1, LineOnOffDash, CapButt,
                       JoinMiter);
    viewFillGC = XCreateGC(dpy, DefaultRootWindow(dpy), 0, 0);
    XSetForeground(dpy, viewFillGC, Qt::white.rgb());
    XSetBackground(dpy, viewFillGC, Qt::white.rgb());
    XSetFillStyle(dpy, viewFillGC, FillSolid);

    connect(this, SIGNAL(lastWindowClosed()), SLOT(quit()));
    appPtr = this;

    browserAfterList = true;

    // Register built-in image formats
    QImageIO::defineIOHandler("XCF",
                              "gimp xcf",
                              0,
                              qimageio_readXCF,
                              NULL);
    KImageIO::registerFormats();

    globalData = new PixieGlobal();

    magickProgress = NULL;
    magickLbl = NULL;
    SetMonitorHandler(magickMonitor);
    SetWarningHandler(magickWarning);
    SetErrorHandler(magickError);
    SetFatalErrorHandler(magickFatalError);
    XSetIOErrorHandler(xioErrorHandler);
}

KIFApplication::~KIFApplication()
{
    if(catMgr)
        delete catMgr;
    XFreeGC(QPaintDevice::x11AppDisplay(), rubberBandGC);
    XFreeGC(QPaintDevice::x11AppDisplay(), viewFillGC);
    delete globalData;
    clearData();
}

PixieGlobal* KIFApplication::globals()
{
    return(globalData);
}

void KIFApplication::setMPlayerWindow(int playerid, int frameid)
{
    mplayerWindow = playerid;
    mplayerFrameWindow = frameid;
}

CatagoryManager* KIFApplication::catagoryManager()
{
    return(catMgr);
}

void KIFApplication::hideWindows()
{
    emit hideAllWindows();
}

void KIFApplication::showWindows()
{
    emit showAllWindows();
}

void KIFApplication::runInitialFileList(KIFFileList *fileList)
{
    list = fileList;
    imageBuffer = new KIFImage(this);
    connect(fileList, SIGNAL(selected(QListBoxItem *)), this,
            SLOT(slotFileListSelected(QListBoxItem *)));

    KConfig *config = KGlobal::config();
    config->setGroup("UISettings");
    int viewMode = config->readNumEntry("ViewMode", 0);
    if(viewMode == 0){
        KIFScaledTopLevel *scaledTopLevel = new KIFScaledTopLevel(imageBuffer, NULL);
        connect(scaledTopLevel, SIGNAL(selectionChanged(const QRect &)),
                imageBuffer, SLOT(slotSelectionChanged(const QRect &)));
        connect(scaledTopLevel, SIGNAL(prevList()), fileList,
                SLOT(slotPrevInList()));
        connect(scaledTopLevel, SIGNAL(nextList()), fileList,
                SLOT(slotNextInList()));

        connect(scaledTopLevel, SIGNAL(finished()), this,
                SLOT(slotFileListFinished()));
        viewer = scaledTopLevel;
    }
    else if(viewMode == 1){
        KIFScrollTopLevel *scrollTopLevel = new KIFScrollTopLevel(imageBuffer, NULL);
        connect(scrollTopLevel, SIGNAL(prevList()), fileList,
                SLOT(slotPrevInList()));
        connect(scrollTopLevel, SIGNAL(nextList()), fileList,
                SLOT(slotNextInList()));

        connect(scrollTopLevel, SIGNAL(finished()), this,
                SLOT(slotFileListFinished()));
        viewer = scrollTopLevel;
    }
    else if(viewMode == 2){
        KIFFullScreen *fullScreenTopLevel = new KIFFullScreen(imageBuffer, false, NULL,
                                                              NULL, false);
        connect(fullScreenTopLevel, SIGNAL(prevList()), fileList,
                SLOT(slotPrevInList()));
        connect(fullScreenTopLevel, SIGNAL(nextList()), fileList,
                SLOT(slotNextInList()));
        connect(fullScreenTopLevel, SIGNAL(finished()), this,
                SLOT(slotFileListFinished()));
        viewer = fullScreenTopLevel;
    }
    else if(viewMode == 3){
        KIFFullScreen *fullScreenTopLevel = new KIFFullScreen(imageBuffer, true, NULL,
                                                             NULL, false);
        connect(fullScreenTopLevel, SIGNAL(prevList()), fileList,
                SLOT(slotPrevInList()));
        connect(fullScreenTopLevel, SIGNAL(nextList()), fileList,
                SLOT(slotNextInList()));
        connect(fullScreenTopLevel, SIGNAL(finished()), this,
                SLOT(slotFileListFinished()));
        viewer = fullScreenTopLevel;
    }
    viewer->show();
    QListBoxItem *i = fileList->item(0);
    fileList->setCurrentItem(i);
    fileList->setSelected(i, true);
    imageBuffer->slotSetFile(((KIFImageListItem *)i)->fileName());
}

void KIFApplication::slotFileListFinished()
{
    delete viewer;
    delete imageBuffer;
    if(browserAfterList){
        loadBrowser(list);
        delete list;
    }
    else
        quit();
}

void KIFApplication::slotFileListSelected(QListBoxItem *i)
{
    imageBuffer->slotSetFile(((KIFImageListItem *)i)->fileName());
}

void KIFApplication::loadEditor(const QString &/*fileStr*/)
{
    return;
}

void KIFApplication::loadBrowser(KIFFileList */*fileList*/)
{
    if(!catMgr)
        catMgr = new CatagoryManager;

    UIManager *w = new UIManager(list);
    w->show();
}

bool KIFApplication::x11EventFilter(XEvent *ev)
{
    if(ev->xany.window != ((Window)0) && ev->xany.window == (Window)mplayerWindow){
        if(ev->type == UnmapNotify)
            return(true);
    }
    else if(ev->xany.window != ((Window)0) && ev->xany.window == (Window)mplayerFrameWindow){
        if(ev->type == Expose || ev->type == MapRequest ||
           ev->type == ConfigureNotify){
            //XResizeWindow(QPaintDevice::x11AppDisplay(), mplayerWindow,
            //              300, 300);
            XMapRaised(QPaintDevice::x11AppDisplay(), mplayerWindow);
        }
    }
    return(false);
}

QLabel* KIFApplication::magickMessageLabel()
{
    return(magickLbl);
}

KProgress* KIFApplication::magickMessageProgress()
{
    return(magickProgress);
}

void KIFApplication::setMagickMessageWidgets(KProgress *progress,
                                             QLabel *label)
{
    magickProgress = progress;
    magickLbl = label;
}

int xioErrorHandler(Display */*dpy*/)
{
    qWarning("Got fatal X Error! Freeing shared memory.");
    clearData();
    exit(1);
    return(0);
}


