#include "ifapp.h"
#include "filelist.h"
#include "imageutils.h"
#include <qfileinfo.h>
#include <qdir.h>
#include <qtextstream.h>
#include <kmessagebox.h>
#include <kurl.h>
#include <kmimetype.h>
#include <kcmdlineargs.h>
#include <kaboutdata.h>
#include <klocale.h>

#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
// ImageMagick redefines off_t to long long
#undef off_t
#define off_t long long
extern "C"{
#include <magick/api.h>
};


/* Signal handlers. We install them for pretty much everything that can
 * possibly go wrong, even if not really needed, because we have allocated
 * shared memory that MUST be deleted.
 */

void crashHandler(int id);
void installSignalHandlers();

struct sigaction sighup_handler, sigkill_handler, sigill_handler,
    sigsegv_handler, sigfpe_handler, sigabrt_handler, sigint_handler,
    sigterm_handler;

static const char *description =
	I18N_NOOP("PixiePlus Image and Photo manager.");

static KCmdLineOptions options[] =
{
    { "a", 0, 0},
    { "all", I18N_NOOP("Load all images in the current directory"), 0},
    { "d", 0, 0},
    { "dir <file>", I18N_NOOP("Load all images in a given directory"), 0},
    { "m", 0, 0},
    { "mini", I18N_NOOP("Exit after viewing cmdline images (do not load browser plugin)"), 0},
    { "f", 0, 0},
    { "filelist <file>", I18N_NOOP("Load the given FileList file"), 0},
    { "+[file(s)]", I18N_NOOP("File(s) or URL(s) to open"), 0 },
    { 0, 0, 0 }
};

int main( int argc, char **argv )
{
    InitializeMagick(*argv);

    KAboutData aboutData( "pixie", I18N_NOOP("Pixie"),
    "0.5.1", description, KAboutData::License_BSD,
    "(c) 2001-2003 Daniel Duley <mosfet@kde.org>\n"
    "(c) 2003-2004 Arjan van Leeuwen <avleeuwen@piwebs.com>\n"
    "(c) 2004 Chris Howells <howells@kde.org>");
    aboutData.addAuthor("Daniel Duley", "Original Author", "mosfet@kde.org");
    aboutData.addAuthor("Arjan van Leeuwen", "Co-Maintainer", "avleeuwen@piwebs.com");
    aboutData.addAuthor("Chris Howells", "Co-Maintainer", "howells@kde.org");

    KCmdLineArgs::init( argc, argv, &aboutData );
    KCmdLineArgs::addCmdLineOptions(options);

    KIFApplication app(argc, argv);
    installSignalHandlers();
    //outputFormats();

    KIFFileList *fileList = new KIFFileList;
    fileList->hide();

    KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
    if(args->isSet("mini")){
        qWarning("Mini (express) mode is obselete!");
        //app.setBrowserAfterList(false);
    }
    if(args->isSet("filelist")){
        QFile f(args->getOption("filelist"));
        if(f.open(IO_ReadOnly)){
            fileList->clear();
            QTextStream t(&f);
            if(t.readLine() != "PixieList"){
                KMessageBox::error(NULL, i18n("Invalid FileList file."),
                                   i18n("Pixie FileList Error"));
                f.close();
                return(1);
            }
            while (!t.eof()){
                fileList->slotAppend(t.readLine());
            }
            f.close();
        }
        else{
            KMessageBox::error(NULL, i18n("Cannot open FileList file."),
                               i18n("Pixie FileList Error"));
            return(1);
        }
    }
    else{
        for( int i = 0; i < args->count(); i++ ){
            QFileInfo fi(args->arg(i));
            if(fi.isDir())
                QDir::setCurrent(fi.absFilePath());
            else
                fileList->slotAppend(fi.absFilePath());
        }
        if(args->isSet("all") || args->isSet("dir")){
            QDir d(args->isSet("all") ? args->cwd() :
                   args->getOption("dir"));
            if(!d.exists())
                qWarning("Invalid directory specified!");
            else{
                d.setFilter(QDir::Files);
                const QFileInfoList *list = d.entryInfoList();
                QFileInfoListIterator it(*list);
                QFileInfo *fi;
                KURL url;
                while((fi=it.current())){
                    url.setPath(fi->absFilePath());
                    if(KMimeType::findByURL(url, true, true)->name().left(6) ==
                       "image/"){
                        fileList->slotAppend(fi->absFilePath());
                    }
                    ++it;
                }
            }
        }
    }
    if(fileList->count() == 0){
        app.loadBrowser(fileList);
    }
    else
        app.runInitialFileList(fileList);

    /*
    if(args->isSet("thumbnail"))
        w->slotThumbnails(); */
    int result = app.exec();
    DestroyMagick();
    return(result);
}

void installSignalHandlers()
{
    struct sigaction action;
    memset(&action, 0, sizeof(action));
    action.sa_handler = crashHandler;

    sigaction(SIGHUP, &action, &sighup_handler);
    sigaction(SIGKILL, &action, &sigkill_handler);
    sigaction(SIGILL, &action, &sigill_handler);
    sigaction(SIGSEGV, &action, &sigsegv_handler);
    sigaction(SIGFPE, &action, &sigfpe_handler);
    sigaction(SIGABRT, &action, &sigabrt_handler);
    sigaction(SIGINT, &action, &sigint_handler);
    sigaction(SIGTERM, &action, &sigterm_handler);
}

void crashHandler(int id)
{
    qWarning("In signal handler, freeing shared memory...");
    clearData();

    sigaction(SIGHUP, &sighup_handler, 0);
    sigaction(SIGKILL, &sigkill_handler, 0);
    sigaction(SIGILL, &sigill_handler, 0);
    sigaction(SIGSEGV, &sigsegv_handler, 0);
    sigaction(SIGFPE, &sigfpe_handler, 0);
    sigaction(SIGABRT, &sigabrt_handler, 0);
    sigaction(SIGINT, &sigint_handler, 0);
    sigaction(SIGTERM, &sigterm_handler, 0);
    raise(id);
}

