#include <qintdict.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include "imageutils.h"
#include "ifapp.h"
#include "catagorymgr.h"
#include "browser_sort.h"
#include "browser.h"

bool isDuplicateSize(off_t size, PixieBrowser *browser)
{
    // FIXME - make this more efficent. Sort by size first, then look for
    // dupes
    struct dirinfo **listarray = browser->currentListArray();
    int i, count = browser->listArrayCount();
    bool foundSize = false;
    for(i=0; i < count; ++i){
        if(listarray[i]->status.st_size == size){
            if(foundSize)
                return(true);
            foundSize = true;
        }
    }
    return(false);
}

int sortDateAscending(const void *a, const void *b)
{
    const dirinfo **a_dir = (const dirinfo **)a;
    const dirinfo **b_dir = (const dirinfo **)b;
    if(S_ISDIR(a_dir[0]->status.st_mode))
        if(S_ISDIR(b_dir[0]->status.st_mode))
            return(strcasecmp(a_dir[0]->name, b_dir[0]->name));
        else
            return(-1);
    else if(S_ISDIR(b_dir[0]->status.st_mode))
        return(1);

    if(a_dir[0]->browser->placeCatagoriesOnTop()){
        CatInfo *acat = a_dir[0]->browser->catagoryDict()->
            find((long)a_dir[0]->status.st_ino);
        CatInfo *bcat = b_dir[0]->browser->catagoryDict()->
            find((long)b_dir[0]->status.st_ino);
        if(acat || bcat){
            if(!acat)
                return(1);
            else if(!bcat)
                return(-1);
            else if(acat->catagories[0] == bcat->catagories[0])
                return(b_dir[0]->status.st_mtime - a_dir[0]->status.st_mtime);
            else{
                QString **catarray = kifapp()->catagoryManager()->array();
                return(QString::compare(*catarray[acat->catagories[0]],
                                        *catarray[bcat->catagories[0]]));
            }
        }
    }
    else if(a_dir[0]->browser->placeImagesOnTop()){
        if(!a_dir[0]->extensionChecked){
            const_cast<dirinfo*>(a_dir[0])->isImage = isImageType(a_dir[0]->name);
            const_cast<dirinfo*>(a_dir[0])->extensionChecked = true;
        }
        if(!b_dir[0]->extensionChecked){
            const_cast<dirinfo*>(b_dir[0])->isImage = isImageType(b_dir[0]->name);
            const_cast<dirinfo*>(b_dir[0])->extensionChecked = true;
        }
        if(a_dir[0]->isImage){
            if(b_dir[0]->isImage)
                return(b_dir[0]->status.st_mtime - a_dir[0]->status.st_mtime);
            else
                return(-1);
        }
        else if(b_dir[0]->isImage)
            return(1);
    }
    return(b_dir[0]->status.st_mtime - a_dir[0]->status.st_mtime);
}

int sortDateDescending(const void *a, const void *b)
{
    const dirinfo **a_dir = (const dirinfo **)a;
    const dirinfo **b_dir = (const dirinfo **)b;
    if(S_ISDIR(a_dir[0]->status.st_mode))
        if(S_ISDIR(b_dir[0]->status.st_mode))
            return(strcasecmp(a_dir[0]->name, b_dir[0]->name));
        else
            return(-1);
    else if(S_ISDIR(b_dir[0]->status.st_mode))
        return(1);
    if(a_dir[0]->browser->placeCatagoriesOnTop()){
        CatInfo *acat = a_dir[0]->browser->catagoryDict()->
            find((long)a_dir[0]->status.st_ino);
        CatInfo *bcat = b_dir[0]->browser->catagoryDict()->
            find((long)b_dir[0]->status.st_ino);
        if(acat || bcat){
            if(!acat)
                return(1);
            else if(!bcat)
                return(-1);
            else if(acat->catagories[0] == bcat->catagories[0])
                return(a_dir[0]->status.st_mtime - b_dir[0]->status.st_mtime);
            else{
                QString **catarray = kifapp()->catagoryManager()->array();
                return(QString::compare(*catarray[acat->catagories[0]],
                                        *catarray[bcat->catagories[0]]));
            }
        }
    }
    else if(a_dir[0]->browser->placeImagesOnTop()){
        if(!a_dir[0]->extensionChecked){
            const_cast<dirinfo*>(a_dir[0])->isImage = isImageType(a_dir[0]->name);
            const_cast<dirinfo*>(a_dir[0])->extensionChecked = true;
        }
        if(!b_dir[0]->extensionChecked){
            const_cast<dirinfo*>(b_dir[0])->isImage = isImageType(b_dir[0]->name);
            const_cast<dirinfo*>(b_dir[0])->extensionChecked = true;
        }
        if(a_dir[0]->isImage){
            if(b_dir[0]->isImage)
                return(a_dir[0]->status.st_mtime - b_dir[0]->status.st_mtime);
            else
                return(-1);
        }
        else if(b_dir[0]->isImage)
            return(1);
    }
    return(a_dir[0]->status.st_mtime - b_dir[0]->status.st_mtime);
}

int sortNameAscending(const void *a, const void *b)
{
    const dirinfo **a_dir = (const dirinfo **)a;
    const dirinfo **b_dir = (const dirinfo **)b;
    if(S_ISDIR(a_dir[0]->status.st_mode))
        if(S_ISDIR(b_dir[0]->status.st_mode))
            return(strcasecmp(a_dir[0]->name, b_dir[0]->name));
        else
            return(-1);
    else if(S_ISDIR(b_dir[0]->status.st_mode))
        return(1);
    if(a_dir[0]->browser->placeCatagoriesOnTop()){
        CatInfo *acat = a_dir[0]->browser->catagoryDict()->
            find((long)a_dir[0]->status.st_ino);
        CatInfo *bcat = b_dir[0]->browser->catagoryDict()->
            find((long)b_dir[0]->status.st_ino);
        if(acat || bcat){
            if(!acat)
                return(1);
            else if(!bcat)
                return(-1);
            else if(acat->catagories[0] == bcat->catagories[0])
                return(strcasecmp(a_dir[0]->name, b_dir[0]->name));
            else{
                QString **catarray = kifapp()->catagoryManager()->array();
                return(QString::compare(*catarray[acat->catagories[0]],
                                        *catarray[bcat->catagories[0]]));
            }
        }
    }
    else if(a_dir[0]->browser->placeImagesOnTop()){
        if(!a_dir[0]->extensionChecked){
            const_cast<dirinfo*>(a_dir[0])->isImage = isImageType(a_dir[0]->name);
            const_cast<dirinfo*>(a_dir[0])->extensionChecked = true;
        }
        if(!b_dir[0]->extensionChecked){
            const_cast<dirinfo*>(b_dir[0])->isImage = isImageType(b_dir[0]->name);
            const_cast<dirinfo*>(b_dir[0])->extensionChecked = true;
        }
        if(a_dir[0]->isImage){
            if(b_dir[0]->isImage)
                return(strcasecmp(a_dir[0]->name, b_dir[0]->name));
            else
                return(-1);
        }
        else if(b_dir[0]->isImage)
            return(1);
    }
    return(strcasecmp(a_dir[0]->name, b_dir[0]->name));
}

int sortNameDescending(const void *a, const void *b)
{
    const dirinfo **a_dir = (const dirinfo **)a;
    const dirinfo **b_dir = (const dirinfo **)b;
    if(S_ISDIR(a_dir[0]->status.st_mode))
        if(S_ISDIR(b_dir[0]->status.st_mode))
            return(strcasecmp(a_dir[0]->name, b_dir[0]->name));
        else
            return(-1);
    else if(S_ISDIR(b_dir[0]->status.st_mode))
        return(1);
    if(a_dir[0]->browser->placeCatagoriesOnTop()){
        CatInfo *acat = a_dir[0]->browser->catagoryDict()->
            find((long)a_dir[0]->status.st_ino);
        CatInfo *bcat = b_dir[0]->browser->catagoryDict()->
            find((long)b_dir[0]->status.st_ino);
        if(acat || bcat){
            if(!acat)
                return(1);
            else if(!bcat)
                return(-1);
            else if(acat->catagories[0] == bcat->catagories[0])
                return(strcasecmp(b_dir[0]->name, a_dir[0]->name));
            else{
                QString **catarray = kifapp()->catagoryManager()->array();
                return(QString::compare(*catarray[acat->catagories[0]],
                                        *catarray[bcat->catagories[0]]));
            }
        }
    }
    else if(a_dir[0]->browser->placeImagesOnTop()){
        if(!a_dir[0]->extensionChecked){
            const_cast<dirinfo*>(a_dir[0])->isImage = isImageType(a_dir[0]->name);
            const_cast<dirinfo*>(a_dir[0])->extensionChecked = true;
        }
        if(!b_dir[0]->extensionChecked){
            const_cast<dirinfo*>(b_dir[0])->isImage = isImageType(b_dir[0]->name);
            const_cast<dirinfo*>(b_dir[0])->extensionChecked = true;
        }
        if(a_dir[0]->isImage){
            if(b_dir[0]->isImage)
                return(strcasecmp(b_dir[0]->name, a_dir[0]->name));
            else
                return(-1);
        }
        else if(b_dir[0]->isImage)
            return(1);
    }
    return(strcasecmp(b_dir[0]->name, a_dir[0]->name));
}

int sortSizeAscending(const void *a, const void *b)
{
    const dirinfo **a_dir = (const dirinfo **)a;
    const dirinfo **b_dir = (const dirinfo **)b;
    if(S_ISDIR(a_dir[0]->status.st_mode))
        if(S_ISDIR(b_dir[0]->status.st_mode))
            return(strcasecmp(a_dir[0]->name, b_dir[0]->name));
        else
            return(-1);
    else if(S_ISDIR(b_dir[0]->status.st_mode))
        return(1);

    if(a_dir[0]->browser->placeCatagoriesOnTop()){
        CatInfo *acat = a_dir[0]->browser->catagoryDict()->
            find((long)a_dir[0]->status.st_ino);
        CatInfo *bcat = b_dir[0]->browser->catagoryDict()->
            find((long)b_dir[0]->status.st_ino);
        if(acat || bcat){
            if(!acat)
                return(1);
            else if(!bcat)
                return(-1);
            else if(acat->catagories[0] == bcat->catagories[0])
                return(b_dir[0]->status.st_size - a_dir[0]->status.st_size);
            else{
                QString **catarray = kifapp()->catagoryManager()->array();
                return(QString::compare(*catarray[acat->catagories[0]],
                                        *catarray[bcat->catagories[0]]));
            }
        }
    }
    else if(a_dir[0]->browser->placeImagesOnTop()){
        if(!a_dir[0]->extensionChecked){
            const_cast<dirinfo*>(a_dir[0])->isImage = isImageType(a_dir[0]->name);
            const_cast<dirinfo*>(a_dir[0])->extensionChecked = true;
        }
        if(!b_dir[0]->extensionChecked){
            const_cast<dirinfo*>(b_dir[0])->isImage = isImageType(b_dir[0]->name);
            const_cast<dirinfo*>(b_dir[0])->extensionChecked = true;
        }
        if(a_dir[0]->isImage){
            if(b_dir[0]->isImage)
                return(b_dir[0]->status.st_size - a_dir[0]->status.st_size);
            else
                return(-1);
        }
        else if(b_dir[0]->isImage)
            return(1);
    }
    return(b_dir[0]->status.st_size - a_dir[0]->status.st_size);
}

int sortSizeAscendingSameFirst(const void *a, const void *b)
{
    return(sortSizeAscending(a, b));
    /*
    const dirinfo **a_dir = (const dirinfo **)a;
    const dirinfo **b_dir = (const dirinfo **)b;
    if(S_ISDIR(a_dir[0]->status.st_mode))
        if(S_ISDIR(b_dir[0]->status.st_mode))
            return(strcasecmp(a_dir[0]->name, b_dir[0]->name));
        else
            return(-1);
    else if(S_ISDIR(b_dir[0]->status.st_mode))
        return(1);

    bool isDupeA = isDuplicateSize(a_dir[0]->status.st_size,
                                   a_dir[0]->browser);
    bool isDupeB = isDuplicateSize(b_dir[0]->status.st_size,
                                   b_dir[0]->browser);

    if(a_dir[0]->browser->placeCatagoriesOnTop()){
        CatInfo *acat = a_dir[0]->browser->catagoryDict()->
            find((long)a_dir[0]->status.st_ino);
        CatInfo *bcat = b_dir[0]->browser->catagoryDict()->
            find((long)b_dir[0]->status.st_ino);
        if(acat || bcat){
            if(!acat)
                return(1);
            else if(!bcat)
                return(-1);
            else if(acat->catagories[0] == bcat->catagories[0])
                return(b_dir[0]->status.st_size - a_dir[0]->status.st_size);
            else{
                QString **catarray = kifapp()->catagoryManager()->array();
                return(QString::compare(*catarray[acat->catagories[0]],
                                        *catarray[bcat->catagories[0]]));
            }
        }
    }
    else if(a_dir[0]->browser->placeImagesOnTop()){
        if(!a_dir[0]->extensionChecked){
            const_cast<dirinfo*>(a_dir[0])->isImage = isImageType(a_dir[0]->name);
            const_cast<dirinfo*>(a_dir[0])->extensionChecked = true;
        }
        if(!b_dir[0]->extensionChecked){
            const_cast<dirinfo*>(b_dir[0])->isImage = isImageType(b_dir[0]->name);
            const_cast<dirinfo*>(b_dir[0])->extensionChecked = true;
        }
        if(a_dir[0]->isImage){
            if(b_dir[0]->isImage)
                return(b_dir[0]->status.st_size - a_dir[0]->status.st_size);
            else
                return(-1);
        }
        else if(b_dir[0]->isImage)
            return(1);
    }
    return(b_dir[0]->status.st_size - a_dir[0]->status.st_size);
    */
}

int sortSizeDescending(const void *a, const void *b)
{
    const dirinfo **a_dir = (const dirinfo **)a;
    const dirinfo **b_dir = (const dirinfo **)b;
    if(S_ISDIR(a_dir[0]->status.st_mode))
        if(S_ISDIR(b_dir[0]->status.st_mode))
            return(strcasecmp(a_dir[0]->name, b_dir[0]->name));
        else
            return(-1);
    else if(S_ISDIR(b_dir[0]->status.st_mode))
        return(1);

    if(a_dir[0]->browser->placeCatagoriesOnTop()){
        CatInfo *acat = a_dir[0]->browser->catagoryDict()->
            find((long)a_dir[0]->status.st_ino);
        CatInfo *bcat = b_dir[0]->browser->catagoryDict()->
            find((long)b_dir[0]->status.st_ino);
        if(acat || bcat){
            if(!acat)
                return(1);
            else if(!bcat)
                return(-1);
            else if(acat->catagories[0] == bcat->catagories[0])
                return(a_dir[0]->status.st_size - b_dir[0]->status.st_size);
            else{
                QString **catarray = kifapp()->catagoryManager()->array();
                return(QString::compare(*catarray[acat->catagories[0]],
                                        *catarray[bcat->catagories[0]]));
            }
        }
    }
    else if(a_dir[0]->browser->placeImagesOnTop()){
        if(!a_dir[0]->extensionChecked){
            const_cast<dirinfo*>(a_dir[0])->isImage = isImageType(a_dir[0]->name);
            const_cast<dirinfo*>(a_dir[0])->extensionChecked = true;
        }
        if(!b_dir[0]->extensionChecked){
            const_cast<dirinfo*>(b_dir[0])->isImage = isImageType(b_dir[0]->name);
            const_cast<dirinfo*>(b_dir[0])->extensionChecked = true;
        }
        if(a_dir[0]->isImage){
            if(b_dir[0]->isImage)
                return(a_dir[0]->status.st_size - b_dir[0]->status.st_size);
            else
                return(-1);
        }
        else if(b_dir[0]->isImage)
            return(1);
    }
    return(a_dir[0]->status.st_size - b_dir[0]->status.st_size);
}

